package benchmark_test import ( "context" "crypto/ecdsa" "fmt" "testing" "time" "math/big" base "github.com/CaduceusMetaverseProtocol/metaprotocol/gen/proto/go/base/v1" ring "github.com/CaduceusMetaverseProtocol/metaprotocol/gen/proto/go/ring/v1" "github.com/ethereum/go-ethereum/crypto" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" //"google.golang.org/grpc/encoding/proto" //"github.com/protocolbuffers/protobuf-go/proto" "google.golang.org/protobuf/proto" "google.golang.org/protobuf/types/known/anypb" ) var tableTx = []struct { input int }{ {input: 100}, {input: 200}, {input: 500}, {input: 1000}, {input: 2000}, {input: 5000}, {input: 10000}, {input: 20000}, // {input: 50000}, } func RepeatedEthTx(txl int, b *testing.B) { //b.Logf("b.N: %d\n", b.N) local, err := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A") if err != nil { b.Fatal(err) } publicKey := local.Public() publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey) fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA) remote, err := crypto.GenerateKey() if err != nil { b.Fatal(err) } tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local) //txsQueue, err := ProduceOriginalTxByCount(500000) if err != nil { b.Fatal(err) } beginTime := time.Now() b.ResetTimer() b.RunParallel(func(pb *testing.PB) { for pb.Next() { conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { b.Fatal(err) } defer conn.Close() c := ring.NewRingServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() txs := make([]*base.TransactionEth, 0, txl) for i := 0; i < txl; i++ { //tx := <-txsQueue inner := base.EthTxData{ AccountNonce: tx.Nonce(), Price: tx.GasPrice().Bytes(), GasLimit: tx.Gas(), Payload: tx.Data(), } v, r, sigs := tx.RawSignatureValues() inner.V = v.Bytes() inner.R = r.Bytes() inner.S = sigs.Bytes() inner.Amount = tx.Value().Bytes() addr := base.Address{Address: tx.To().Bytes()} inner.Recipient = &addr inner.From = fromAddr.Bytes() txs = append(txs, &base.TransactionEth{Tx: &base.EthTx{Inner: &inner}}) } req := &base.RepeatedEthTx{Txs: txs} out, err := proto.Marshal(req) if err != nil { b.Fatal(err) } b.SetBytes(int64(len(out))) res, err := c.SendRepeatedEthTx(ctx, req) if err != nil { b.Fatal(err) } _ = res // if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 { // b.Fatal(err) // } // onceHash.Do(func() { // b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes()) // }) } }) b.ReportMetric(float64(b.N)/float64(time.Since(beginTime).Seconds()), "tps") } func RepeatedTxEthAsAny(txl int, b *testing.B) { // onceFunc := func() { local, _ := crypto.HexToECDSA("FD5CC6F5E7E2805E920AC5DC83D5AF1106F9C92F0C04F9D5E1FD4261B4B4464A") publicKey := local.Public() publicKeyECDSA, _ := publicKey.(*ecdsa.PublicKey) fromAddr := crypto.PubkeyToAddress(*publicKeyECDSA) remote, _ := crypto.GenerateKey() var err error tx, err := pricedTransaction(crypto.PubkeyToAddress(remote.PublicKey), 0, 100000, big.NewInt(1), local) if err != nil { b.Fatal(err) } //} // once.Do(onceFunc) beginTime := time.Now() b.ResetTimer() // The loop body is executed b.N times total across all goroutines. b.RunParallel(func(pb *testing.PB) { for pb.Next() { conn, err := grpc.Dial("127.0.0.1:9006", grpc.WithTransportCredentials(insecure.NewCredentials())) if err != nil { b.Fatal(err) } defer conn.Close() c := ring.NewRingServiceClient(conn) ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() txs := make([]*base.TransactionEth, 0, txl) for i := 0; i < txl; i++ { inner := base.EthTxData{ AccountNonce: tx.Nonce(), Price: tx.GasPrice().Bytes(), GasLimit: tx.Gas(), Payload: tx.Data(), } v, r, sigs := tx.RawSignatureValues() inner.V = v.Bytes() inner.R = r.Bytes() inner.S = sigs.Bytes() inner.Amount = tx.Value().Bytes() addr := base.Address{Address: tx.To().Bytes()} inner.Recipient = &addr inner.From = fromAddr.Bytes() txs = append(txs, &base.TransactionEth{Tx: &base.EthTx{Inner: &inner}}) } ethTxAsAny, err := anypb.New(&base.RepeatedEthTx{Txs: txs}) if err != nil { b.Fatal(err) } req := &base.Transaction{Tx: ethTxAsAny} out, err := proto.Marshal(req) if err != nil { b.Fatal(err) } b.SetBytes(int64(len(out))) res, err := c.SendTxAsAny(ctx, req) if err != nil { b.Fatal(err) } _ = res // if bytes.Compare(tx.Hash().Bytes(), res.TxHash) != 0 { // b.Fatal(err) // } // onceHash.Do(func() { // b.Logf("response: %x local: %x \n", res.TxHash, tx.Hash().Bytes()) // }) } }) b.ReportMetric(float64(b.N)/float64(time.Since(beginTime).Seconds()), "tps") } // go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 5 | tee old.txt // Small p-values indicate that the two distributions are significantly different. // If the test indicates that there was no significant change between the two benchmarks (defined as p > 0.05), // benchstat displays a single ~ instead of the percent change. /* benchstat -geomean -delta-test utest -html RepeatedEthTx.txt RepeatedTxEthAsAny.txt > utest.html benchstat -geomean -delta-test ttest -html RepeatedEthTx.txt RepeatedTxEthAsAny.txt > ttest.html benchstat -geomean -delta-test none -html RepeatedEthTx.txt RepeatedTxEthAsAny.txt > none.html */ func BenchmarkRepeated(b *testing.B) { for _, v := range tableTx { b.Run(fmt.Sprintf("input_size_%d", v.input), func(b *testing.B) { //go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 30 | tee RepeatedEthTx.txt //RepeatedEthTx(v.input, b) //go test -v -run BenchmarkAnyTxEth -bench BenchmarkRepeated -benchmem -count 30 | tee RepeatedTxEthAsAny.txt RepeatedTxEthAsAny(v.input, b) }) } } // 验证和 b.Run sub-benchmark的时间一致; func Benchmark200RepeatedEthTx(b *testing.B) { RepeatedEthTx(5000, b) } // func BenchmarkRepeatedNew(b *testing.B) { // for _, v := range tableTx { // b.Run(fmt.Sprintf("input_size_%d", v.input), func(b *testing.B) { // RepeatedTxEthAsAny(v.input, b) // }) // } // }