github.com/turingchain2020/turingchain@v1.1.21/system/consensus/solo/solo_test.go (about) 1 // Copyright Turing Corp. 2018 All Rights Reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package solo 6 7 import ( 8 "bytes" 9 "context" 10 "fmt" 11 "io/ioutil" 12 "net/http" 13 _ "net/http/pprof" // 14 "strings" 15 "sync" 16 "sync/atomic" 17 "testing" 18 "time" 19 20 "github.com/turingchain2020/turingchain/common/log/log15" 21 "google.golang.org/grpc" 22 23 "github.com/turingchain2020/turingchain/common" 24 log "github.com/turingchain2020/turingchain/common/log" 25 "github.com/turingchain2020/turingchain/queue" 26 "github.com/turingchain2020/turingchain/rpc/grpcclient" 27 "github.com/decred/base58" 28 b58 "github.com/mr-tron/base58" 29 30 "github.com/turingchain2020/turingchain/types" 31 "github.com/turingchain2020/turingchain/util" 32 "github.com/turingchain2020/turingchain/util/testnode" 33 "github.com/stretchr/testify/assert" 34 35 //加载系统内置store, 不要依赖plugin 36 _ "github.com/turingchain2020/turingchain/system/dapp/init" 37 _ "github.com/turingchain2020/turingchain/system/mempool/init" 38 _ "github.com/turingchain2020/turingchain/system/store/init" 39 ) 40 41 // 执行: go test -cover 42 func TestSolo(t *testing.T) { 43 mock33 := testnode.New("", nil) 44 defer mock33.Close() 45 cfg := mock33.GetClient().GetConfig() 46 txs := util.GenNoneTxs(cfg, mock33.GetGenesisKey(), 10) 47 for i := 0; i < len(txs); i++ { 48 mock33.GetAPI().SendTx(txs[i]) 49 } 50 mock33.WaitHeight(1) 51 txs = util.GenNoneTxs(cfg, mock33.GetGenesisKey(), 10) 52 for i := 0; i < len(txs); i++ { 53 mock33.GetAPI().SendTx(txs[i]) 54 } 55 mock33.WaitHeight(2) 56 } 57 58 func BenchmarkSolo(b *testing.B) { 59 cfg := testnode.GetDefaultConfig() 60 subcfg := cfg.GetSubConfig() 61 solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 1000) 62 assert.Nil(b, err) 63 subcfg.Consensus["solo"] = solocfg 64 mock33 := testnode.NewWithConfig(cfg, nil) 65 defer mock33.Close() 66 txs := util.GenCoinsTxs(cfg, mock33.GetGenesisKey(), int64(b.N)) 67 var last []byte 68 var mu sync.Mutex 69 b.ResetTimer() 70 done := make(chan struct{}, 10) 71 for i := 0; i < 10; i++ { 72 go func(index int) { 73 for n := index; n < b.N; n += 10 { 74 reply, err := mock33.GetAPI().SendTx(txs[n]) 75 if err != nil { 76 assert.Nil(b, err) 77 } 78 mu.Lock() 79 last = reply.GetMsg() 80 mu.Unlock() 81 } 82 done <- struct{}{} 83 }(i) 84 } 85 for i := 0; i < 10; i++ { 86 <-done 87 } 88 mock33.WaitTx(last) 89 } 90 91 var ( 92 tlog = log15.New("module", "test solo") 93 ) 94 95 //mempool发送交易 10000tx/s 96 func BenchmarkSendTx(b *testing.B) { 97 if testing.Short() { 98 b.Skip("skipping in short mode.") 99 } 100 cfg := testnode.GetDefaultConfig() 101 subcfg := cfg.GetSubConfig() 102 cfg.GetModuleConfig().Exec.DisableAddrIndex = true 103 solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 100) 104 assert.Nil(b, err) 105 solocfg, err = types.ModifySubConfig(solocfg, "benchMode", true) 106 assert.Nil(b, err) 107 subcfg.Consensus["solo"] = solocfg 108 cfg.GetModuleConfig().RPC.JrpcBindAddr = "localhost:9671" 109 cfg.GetModuleConfig().RPC.GrpcBindAddr = "localhost:9672" 110 mock33 := testnode.NewWithRPC(cfg, nil) 111 log.SetLogLevel("error") 112 defer mock33.Close() 113 priv := mock33.GetGenesisKey() 114 b.ResetTimer() 115 b.Run("SendTx-Internal", func(b *testing.B) { 116 b.RunParallel(func(pb *testing.PB) { 117 for pb.Next() { 118 tx := util.CreateNoneTxWithTxHeight(cfg, priv, types.LowAllowPackHeight/2) 119 mock33.GetAPI().SendTx(tx) 120 } 121 }) 122 }) 123 124 b.Run("SendTx-GRPC", func(b *testing.B) { 125 gcli, _ := grpcclient.NewMainChainClient(cfg, "localhost:9672") 126 b.RunParallel(func(pb *testing.PB) { 127 for pb.Next() { 128 tx := util.CreateNoneTxWithTxHeight(cfg, priv, types.LowAllowPackHeight/2) 129 _, err := gcli.SendTransaction(context.Background(), tx) 130 if err != nil { 131 tlog.Error("sendtx grpc", "err", err) 132 } 133 } 134 }) 135 }) 136 137 http.DefaultTransport.(*http.Transport).MaxIdleConnsPerHost = 100 138 defer http.DefaultClient.CloseIdleConnections() 139 b.Run("SendTx-JSONRPC", func(b *testing.B) { 140 b.RunParallel(func(pb *testing.PB) { 141 for pb.Next() { 142 tx := util.CreateNoneTxWithTxHeight(cfg, priv, types.LowAllowPackHeight/2) 143 poststr := fmt.Sprintf(`{"jsonrpc":"2.0","id":2,"method":"Turingchain.SendTransaction","params":[{"data":"%v"}]}`, 144 common.ToHex(types.Encode(tx))) 145 146 resp, _ := http.Post("http://localhost:9671", "application/json", bytes.NewBufferString(poststr)) 147 ioutil.ReadAll(resp.Body) 148 resp.Body.Close() 149 } 150 }) 151 }) 152 } 153 154 //测试每10000笔交易打包的并发时间 3500tx/s 155 func BenchmarkSoloNewBlock(b *testing.B) { 156 if testing.Short() { 157 b.Skip("skipping in short mode.") 158 } 159 cfg := testnode.GetDefaultConfig() 160 cfg.GetModuleConfig().Exec.DisableAddrIndex = true 161 cfg.GetModuleConfig().Mempool.DisableExecCheck = true 162 cfg.GetModuleConfig().RPC.GrpcBindAddr = "localhost:9672" 163 subcfg := cfg.GetSubConfig() 164 solocfg, err := types.ModifySubConfig(subcfg.Consensus["solo"], "waitTxMs", 100) 165 assert.Nil(b, err) 166 solocfg, err = types.ModifySubConfig(solocfg, "benchMode", true) 167 assert.Nil(b, err) 168 subcfg.Consensus["solo"] = solocfg 169 mock33 := testnode.NewWithRPC(cfg, nil) 170 defer mock33.Close() 171 start := make(chan struct{}) 172 //pub := mock33.GetGenesisKey().PubKey().Bytes() 173 var height int64 174 for i := 0; i < 10; i++ { 175 addr, _ := util.Genaddress() 176 go func(addr string) { 177 start <- struct{}{} 178 conn, err := grpc.Dial("localhost:9672", grpc.WithInsecure()) 179 if err != nil { 180 panic(err.Error()) 181 } 182 defer conn.Close() 183 gcli := types.NewTuringchainClient(conn) 184 for { 185 tx := util.CreateNoneTxWithTxHeight(cfg, mock33.GetGenesisKey(), atomic.LoadInt64(&height)+types.LowAllowPackHeight/2) 186 //测试去签名情况 187 //tx := util.CreateNoneTxWithTxHeight(cfg, nil, 0) 188 //tx.Signature = &types.Signature{ 189 // Ty: types.SECP256K1, 190 // Pubkey:pub, 191 //} 192 _, err := gcli.SendTransaction(context.Background(), tx) 193 //_, err := mock33.GetAPI().SendTx(tx) 194 if err != nil { 195 if strings.Contains(err.Error(), "ErrChannelClosed") { 196 return 197 } 198 tlog.Error("sendtx", "err", err.Error()) 199 time.Sleep(2 * time.Second) 200 continue 201 } 202 } 203 }(addr) 204 <-start 205 } 206 b.ResetTimer() 207 for i := 0; i < b.N; i++ { 208 err := mock33.WaitHeight(int64(i + 1)) 209 for err != nil { 210 b.Log("SoloNewBlock", "waitblkerr", err) 211 time.Sleep(time.Second / 10) 212 err = mock33.WaitHeight(int64(i + 1)) 213 } 214 atomic.AddInt64(&height, 1) 215 } 216 } 217 218 // 交易签名性能测试 单核4k 219 func BenchmarkTxSign(b *testing.B) { 220 if testing.Short() { 221 b.Skip("skipping in short mode.") 222 } 223 cfg := testnode.GetDefaultConfig() 224 txBenchNum := 10000 225 _, priv := util.Genaddress() 226 txs := util.GenCoinsTxs(cfg, priv, int64(txBenchNum)) 227 228 start := make(chan struct{}) 229 wait := make(chan struct{}) 230 result := make(chan interface{}, txBenchNum) 231 //控制并发协程数量 232 for i := 0; i < 8; i++ { 233 go func() { 234 wait <- struct{}{} 235 index := 0 236 <-start 237 for { 238 //txs[index%txBenchNum].Sign(types.SECP256K1, priv) 239 result <- txs[index%txBenchNum].CheckSign() 240 index++ 241 } 242 }() 243 <-wait 244 } 245 b.ResetTimer() 246 close(start) 247 for i := 0; i < b.N; i++ { 248 <-result 249 } 250 } 251 252 //消息队列发送性能, 80w /s 253 func BenchmarkMsgQueue(b *testing.B) { 254 if testing.Short() { 255 b.Skip("skipping in short mode.") 256 } 257 cfg := testnode.GetDefaultConfig() 258 q := queue.New("channel") 259 q.SetConfig(cfg) 260 topicNum := 10 261 topics := make([]string, topicNum) 262 start := make(chan struct{}) 263 for i := 0; i < topicNum; i++ { 264 topics[i] = fmt.Sprintf("bench-%d", i) 265 go func(topic string) { 266 start <- struct{}{} 267 client := q.Client() 268 client.Sub(topic) 269 for range client.Recv() { 270 } 271 }(topics[i]) 272 <-start 273 } 274 _, priv := util.Genaddress() 275 txs := util.GenCoinsTxs(cfg, priv, 1) 276 sendCli := q.Client() 277 b.ResetTimer() 278 b.RunParallel(func(pb *testing.PB) { 279 i := 0 280 for pb.Next() { 281 msg := sendCli.NewMessage(topics[i%topicNum], int64(i), txs[0]) 282 err := sendCli.Send(msg, false) 283 assert.Nil(b, err) 284 i++ 285 } 286 }) 287 } 288 289 func BenchmarkTxHash(b *testing.B) { 290 if testing.Short() { 291 b.Skip("skipping in short mode.") 292 } 293 cfg := testnode.GetDefaultConfig() 294 _, priv := util.Genaddress() 295 txs := util.GenCoinsTxs(cfg, priv, 1) 296 b.ResetTimer() 297 for i := 0; i < b.N; i++ { 298 txs[0].Hash() 299 } 300 } 301 302 func BenchmarkEncode(b *testing.B) { 303 304 if testing.Short() { 305 b.Skip("skipping in short mode.") 306 } 307 cfg := testnode.GetDefaultConfig() 308 _, priv := util.Genaddress() 309 txs := util.GenCoinsTxs(cfg, priv, 10000) 310 311 block := &types.Block{} 312 block.Txs = txs 313 b.ResetTimer() 314 for i := 0; i < b.N; i++ { 315 types.Encode(block) 316 } 317 } 318 319 func BenchmarkBase58(b *testing.B) { 320 321 if testing.Short() { 322 b.Skip("skipping in short mode.") 323 } 324 addr := "12qyocayNF7Lv6C9qW4avxs2E7U41fKSfv" 325 buf := base58.Decode(addr) 326 b.ResetTimer() 327 b.Run("decred-base58", func(b *testing.B) { 328 for i := 0; i < b.N; i++ { 329 base58.Encode(buf) 330 } 331 }) 332 333 b.Run("mr-tron-base58", func(b *testing.B) { 334 for i := 0; i < b.N; i++ { 335 b58.Encode(buf) 336 } 337 }) 338 }