github.com/igggame/nebulas-go@v2.1.0+incompatible/cmd/network/main.go (about) 1 // Copyright (C) 2018 go-nebulas authors 2 // 3 // This file is part of the go-nebulas library. 4 // 5 // the go-nebulas library is free software: you can redistribute it and/or modify 6 // it under the terms of the GNU General Public License as published by 7 // the Free Software Foundation, either version 3 of the License, or 8 // (at your option) any later version. 9 // 10 // the go-nebulas library is distributed in the hope that it will be useful, 11 // but WITHOUT ANY WARRANTY; without even the implied warranty of 12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 // GNU General Public License for more details. 14 // 15 // You should have received a copy of the GNU General Public License 16 // along with the go-nebulas library. If not, see <http://www.gnu.org/licenses/>. 17 // 18 19 package main 20 21 import ( 22 "flag" 23 "fmt" 24 "log" 25 "math/rand" 26 "os" 27 "runtime" 28 "runtime/pprof" 29 "time" 30 31 "github.com/libp2p/go-libp2p-interface-conn" 32 "github.com/nebulasio/go-nebulas/core" 33 "github.com/nebulasio/go-nebulas/metrics" 34 "github.com/nebulasio/go-nebulas/neblet" 35 "github.com/nebulasio/go-nebulas/net" 36 "github.com/nebulasio/go-nebulas/util/byteutils" 37 "github.com/nebulasio/go-nebulas/util/logging" 38 ) 39 40 // Message Type 41 var ( 42 PingMessage = "ping" 43 PongMessage = "pong" 44 messageCh = make(chan net.Message, 4096) 45 46 cpuprofile = flag.String("cpuprofile", "", "write cpu profile `file`") 47 memprofile = flag.String("memprofile", "", "write memory profile to `file`") 48 packageSize = flag.Int64("package_size", 0, "package size, default is 0") 49 concurrentCount = flag.Int64("concurrent", 0, "concurrent count, default is 0") 50 limitCount = flag.Int64("limit", 0, "limits of sent message, default is 0, no limit") 51 ) 52 53 func main() { 54 flag.Parse() 55 56 if *cpuprofile != "" { 57 f, err := os.Create(*cpuprofile) 58 if err != nil { 59 log.Fatal("could not create CPU profile: ", err) 60 } 61 if err := pprof.StartCPUProfile(f); err != nil { 62 log.Fatal("could not start CPU profile: ", err) 63 } 64 defer pprof.StopCPUProfile() 65 } 66 67 // fmt.Printf("%v", flag.Args()) 68 if len(flag.Args()) < 2 { 69 help() 70 return 71 } 72 73 // when set to false, NodeID check in stream.go should be ignore. 74 conn.EncryptConnections = true 75 76 // rand. 77 rand.Seed(time.Now().UnixNano()) 78 79 // mode 80 mode := flag.Args()[0] 81 configPath := flag.Args()[1] 82 83 run(mode, configPath, *packageSize, *concurrentCount, *limitCount) 84 85 fmt.Printf("done...") 86 87 if *memprofile != "" { 88 f, err := os.Create(*memprofile) 89 if err != nil { 90 log.Fatal("could not create memory profile: ", err) 91 } 92 runtime.GC() // get up-to-date statistics 93 if err := pprof.WriteHeapProfile(f); err != nil { 94 log.Fatal("could not write memory profile: ", err) 95 } 96 f.Close() 97 } 98 } 99 100 func help() { 101 fmt.Printf("%s [server|client] [config] [package size]\n", os.Args[0]) 102 os.Exit(1) 103 } 104 105 func run(mode, configPath string, packageSize, concurrentMessageCount, totalMessageCount int64) { 106 // config. 107 config := neblet.LoadConfig(configPath) 108 109 // init log. 110 logging.Init(config.App.LogFile, config.App.LogLevel, config.App.LogAge) 111 112 core.SetCompatibilityOptions(config.Chain.ChainId) 113 114 // neblet. 115 neblet, _ := neblet.New(config) 116 netService, err := net.NewNebService(neblet) 117 118 if err != nil { 119 fmt.Printf("Error: %s", err) 120 os.Exit(1) 121 } 122 123 // register dispatcher. 124 netService.Register(net.NewSubscriber(netService, messageCh, false, PingMessage, net.MessageWeightZero)) 125 netService.Register(net.NewSubscriber(netService, messageCh, false, PongMessage, net.MessageWeightZero)) 126 127 // start server. 128 netService.Start() 129 130 // metrics. 131 tps := metrics.NewMeter("tps") 132 throughput := metrics.NewMeter("throughput") 133 latency := metrics.NewHistogramWithUniformSample("latency", 100) 134 135 sentMessageCount := int64(0) 136 137 // first trigger. 138 if mode == "client" { 139 sentMessageCount += concurrentMessageCount 140 time.Sleep(10 * time.Second) 141 go func() { 142 for i := 0; i < int(concurrentMessageCount); i++ { 143 netService.SendMessageToPeers(PingMessage, GenerateData(packageSize), net.MessagePriorityNormal, new(net.ChainSyncPeersFilter)) 144 } 145 }() 146 } 147 148 ticker := time.NewTicker(5 * time.Second) 149 150 for { 151 select { 152 case message := <-messageCh: 153 messageName := message.MessageType() 154 switch messageName { 155 case PingMessage: 156 data := message.Data() 157 sendAt := ParseData(data) 158 nowAt := time.Now().UnixNano() 159 160 latencyVal := (nowAt - sendAt) / int64(1000000) 161 162 // metrics. 163 tps.Mark(1) 164 throughput.Mark(1 * int64(net.NebMessageHeaderLength+len(data))) 165 latency.Update(latencyVal) 166 167 netService.SendMessageToPeer(PongMessage, message.Data(), net.MessagePriorityNormal, message.MessageFrom()) 168 case PongMessage: 169 data := message.Data() 170 sendAt := ParseData(data) 171 nowAt := time.Now().UnixNano() 172 latencyVal := (nowAt - sendAt) / int64(1000000) 173 174 // metrics. 175 tps.Mark(1) 176 throughput.Mark(1 * int64(net.NebMessageHeaderLength+len(data))) 177 latency.Update(latencyVal) 178 179 sentMessageCount++ 180 if totalMessageCount > 0 && sentMessageCount >= totalMessageCount { 181 return 182 } 183 184 netService.SendMessageToPeer(PingMessage, GenerateData(packageSize), net.MessagePriorityNormal, message.MessageFrom()) 185 } 186 case <-ticker.C: 187 fmt.Printf("[Perf] tps: %6.2f/s; throughput: %6.2fk/s; latency p95: %6.2f\n", tps.Rate1(), throughput.Rate1()/1000, latency.Percentile(float64(0.50))) 188 } 189 } 190 } 191 192 // ParseData parse int64 from bytes 193 func ParseData(data []byte) int64 { 194 return byteutils.Int64(data) 195 } 196 197 // GenerateData convert int64 into bytes 198 func GenerateData(packageSize int64) []byte { 199 data := make([]byte, 8+packageSize) 200 copy(data, byteutils.FromInt64(time.Now().UnixNano())) 201 return data 202 }