From 92a702d7f1cf01c6afc6c7b02313a8c5916816db Mon Sep 17 00:00:00 2001 From: Nikolay Nedkov Date: Fri, 17 Feb 2023 17:01:39 +0200 Subject: [PATCH 1/2] adding benchmark tests scripts Signed-off-by: Nikolay Nedkov --- .gitignore | 2 +- .../sequencer/common/metrics/metrics.go | 34 ++++++--- .../sequencer/common/shared/constants.go | 2 + .../common/transactions/transactions.go | 48 ++++++++---- .../pool_processing_erc20_test.go | 46 ++--------- .../sequencer/erc20-transfers/tx_sender.go | 30 ++++++++ .../eth-transfers/pool_processing_eth_test.go | 58 +++----------- .../sequencer/eth-transfers/tx_sender.go | 37 +++++++++ .../sequencer/scripts/clients/init.go | 76 +++++++++++++++++++ .../sequencer/scripts/common/constants.go | 22 ++++++ .../sequencer/scripts/erc20-transfers/main.go | 45 +++++++++++ .../sequencer/scripts/eth-transfers/main.go | 46 +++++++++++ 12 files changed, 331 insertions(+), 115 deletions(-) create mode 100644 test/benchmarks/sequencer/erc20-transfers/tx_sender.go create mode 100644 test/benchmarks/sequencer/eth-transfers/tx_sender.go create mode 100644 test/benchmarks/sequencer/scripts/clients/init.go create mode 100644 test/benchmarks/sequencer/scripts/common/constants.go create mode 100644 test/benchmarks/sequencer/scripts/erc20-transfers/main.go create mode 100644 test/benchmarks/sequencer/scripts/eth-transfers/main.go diff --git a/.gitignore b/.gitignore index c3528621b2..f58fd80ca0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,7 +13,7 @@ **/.DS_Store .vscode .idea/ - +.env out.dat cmd/__debug_bin \ No newline at end of file diff --git a/test/benchmarks/sequencer/common/metrics/metrics.go b/test/benchmarks/sequencer/common/metrics/metrics.go index a8f6bfe8f2..484158afbe 100644 --- a/test/benchmarks/sequencer/common/metrics/metrics.go +++ b/test/benchmarks/sequencer/common/metrics/metrics.go @@ -21,22 +21,32 @@ const ( // CalculateAndPrint calculates and prints the results func CalculateAndPrint(prometheusResp *http.Response, profilingResult string, elapsed time.Duration, sequencerTimeSub, executorTimeSub float64, nTxs int) { - sequencerTime, executorTime, workerTime, err := GetValues(prometheusResp) - if err != nil { - log.Fatalf("error getting prometheus metrics: %v", err) + var ( + sequencerTime, executorTime, workerTime float64 + err error + ) + if prometheusResp != nil { + sequencerTime, executorTime, workerTime, err = GetValues(prometheusResp) + if err != nil { + log.Fatalf("error getting prometheus metrics: %v", err) + } } log.Info("##########") log.Info("# Result #") log.Info("##########") - log.Infof("Total time took for the sequencer To select all txs from the pool: %v", elapsed) - log.Info("######################") - log.Info("# Prometheus Metrics #") - log.Info("######################") - actualTotalTime := sequencerTime - sequencerTimeSub - actualExecutorTime := executorTime - executorTimeSub - PrintPrometheus(actualTotalTime, actualExecutorTime, workerTime) - log.Infof("[Transactions per second]: %v", float64(nTxs)/actualTotalTime) + log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) + + if prometheusResp != nil { + log.Info("######################") + log.Info("# Prometheus Metrics #") + log.Info("######################") + actualTotalTime := sequencerTime - sequencerTimeSub + actualExecutorTime := executorTime - executorTimeSub + PrintPrometheus(actualTotalTime, actualExecutorTime, workerTime) + log.Infof("[Transactions per second]: %v", float64(nTxs)/actualTotalTime) + + } if profilingResult != "" { log.Info("#####################") log.Info("# Profiling Metrics #") @@ -90,7 +100,7 @@ func FetchPrometheus() (*http.Response, error) { func FetchProfiling() (string, error) { fullUrl := fmt.Sprintf("http://localhost:%d%s", profilingPort, metricsLib.ProfileEndpoint) log.Infof("Fetching profiling metrics from: %s ...", fullUrl) - cmd := exec.Command("go", "tool", "pprof", "-top", fullUrl) + cmd := exec.Command("go", "tool", "pprof", "-show=sequencer", "-top", fullUrl) out, err := cmd.CombinedOutput() if err != nil { log.Fatalf("Error running pprof: %v\n%s", err, out) diff --git a/test/benchmarks/sequencer/common/shared/constants.go b/test/benchmarks/sequencer/common/shared/constants.go index c628a79e33..3daecf058b 100644 --- a/test/benchmarks/sequencer/common/shared/constants.go +++ b/test/benchmarks/sequencer/common/shared/constants.go @@ -11,4 +11,6 @@ const ( MaxCumulativeGasUsed = 80000000000 // PrometheusPort is the port where prometheus is running PrometheusPort = 9092 + // NumberOfTxs is the number of transactions to send + NumberOfTxs = 1000 ) diff --git a/test/benchmarks/sequencer/common/transactions/transactions.go b/test/benchmarks/sequencer/common/transactions/transactions.go index d919f25e48..c51dd41fde 100644 --- a/test/benchmarks/sequencer/common/transactions/transactions.go +++ b/test/benchmarks/sequencer/common/transactions/transactions.go @@ -2,8 +2,8 @@ package transactions import ( "context" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "math/big" - "testing" "time" "github.com/0xPolygonHermez/zkevm-node/log" @@ -11,34 +11,34 @@ import ( "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" "github.com/0xPolygonHermez/zkevm-node/test/operations" "github.com/ethereum/go-ethereum/ethclient" - "github.com/stretchr/testify/require" ) // SendAndWait sends a number of transactions and waits for them to be marked as pending in the pool func SendAndWait( - b *testing.B, + ctx context.Context, + auth *bind.TransactOpts, senderNonce uint64, client *ethclient.Client, - gasPrice *big.Int, - pl *pool.Pool, - ctx context.Context, + countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), nTxs int, - txSenderFunc func(b *testing.B, l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64), -) { - shared.Auth.GasPrice = gasPrice - shared.Auth.GasLimit = 2100000 + txSenderFunc func(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) error, +) error { + auth.GasLimit = 2100000 log.Debugf("Sending %d txs ...", nTxs) maxNonce := uint64(nTxs) + senderNonce for nonce := senderNonce; nonce < maxNonce; nonce++ { - txSenderFunc(b, client, gasPrice, nonce) + err := txSenderFunc(client, auth.GasPrice, nonce) + if err != nil { + return err + } } log.Debug("All txs were sent!") log.Debug("Waiting pending transactions To be added in the pool ...") err := operations.Poll(1*time.Second, shared.DefaultDeadline, func() (bool, error) { // using a closure here To capture st and currentBatchNumber - count, err := pl.CountPendingTransactions(ctx) + count, err := countByStatusFunc(ctx, pool.TxStatusPending) if err != nil { return false, err } @@ -47,6 +47,28 @@ func SendAndWait( done := count == uint64(nTxs) return done, nil }) - require.NoError(b, err) + if err != nil { + return err + } + log.Debug("All pending txs are added in the pool!") + + return nil +} + +func WaitStatusSelected(countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), nTxs uint64) (error, time.Duration) { + start := time.Now() + log.Debug("Wait for sequencer to select all txs from the pool") + err := operations.Poll(200*time.Millisecond, shared.DefaultDeadline, func() (bool, error) { + selectedCount, err := countByStatusFunc(shared.Ctx, pool.TxStatusSelected) + if err != nil { + return false, err + } + + log.Debugf("amount of selected txs: %d", selectedCount) + done := selectedCount >= nTxs + return done, nil + }) + elapsed := time.Since(start) + return err, elapsed } diff --git a/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go b/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go index 03cb624949..69b590cef7 100644 --- a/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go +++ b/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go @@ -3,14 +3,11 @@ package erc20_transfers import ( "context" "fmt" - "math/big" "net/http" "testing" "time" - "github.com/0xPolygonHermez/zkevm-node/encoding" "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/metrics" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/setup" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" @@ -23,15 +20,8 @@ import ( ) const ( - nTxs = 100 txTimeout = 60 * time.Second - profilingEnabled = true -) - -var ( - mintAmount, _ = big.NewInt(0).SetString("1000000000000000000000", encoding.Base10) - transferAmount = big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Div(mintAmount, big.NewInt(nTxs)), big.NewInt(90)), big.NewInt(100)) - erc20SC *ERC20.ERC20 + profilingEnabled = false ) func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { @@ -47,8 +37,8 @@ func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { if err != nil { return } - - transactions.SendAndWait(b, senderNonce, client, gasPrice, pl, shared.Ctx, nTxs, runERC20TxSender) + shared.Auth.GasPrice = gasPrice + err = transactions.SendAndWait(shared.Ctx, shared.Auth, senderNonce, client, pl.CountTransactionsByStatus, shared.NumberOfTxs, TxSender) require.NoError(b, err) var ( @@ -56,22 +46,10 @@ func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { response *http.Response ) - b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", nTxs), func(b *testing.B) { + b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", shared.NumberOfTxs), func(b *testing.B) { // Wait all txs to be selected by the sequencer - start := time.Now() - log.Debug("Wait for sequencer to select all txs from the pool") - err := operations.Poll(1*time.Second, shared.DefaultDeadline, func() (bool, error) { - selectedCount, err := pl.CountTransactionsByStatus(shared.Ctx, pool.TxStatusSelected) - if err != nil { - return false, err - } - - log.Debugf("amount of selected txs: %d", selectedCount) - done := selectedCount >= nTxs - return done, nil - }) + err, _ := transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) require.NoError(b, err) - elapsed = time.Since(start) response, err = metrics.FetchPrometheus() require.NoError(b, err) }) @@ -87,7 +65,7 @@ func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { log.Errorf("failed to teardown: %s", err) } - metrics.CalculateAndPrint(response, profilingResult, elapsed-deploySCElapsed, deploySCSequencerTime, deploySCExecutorOnlyTime, nTxs) + metrics.CalculateAndPrint(response, profilingResult, elapsed-deploySCElapsed, deploySCSequencerTime, deploySCExecutorOnlyTime, shared.NumberOfTxs) log.Infof("########################################") log.Infof("# Deploying ERC20 SC and Mint Tx took: #") log.Infof("########################################") @@ -111,15 +89,3 @@ func deployERC20Contract(b *testing.B, client *ethclient.Client, ctx context.Con require.NoError(b, err) return err } - -func runERC20TxSender(b *testing.B, l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) { - log.Debugf("sending nonce: %d", nonce) - var actualTransferAmount *big.Int - if nonce%2 == 0 { - actualTransferAmount = big.NewInt(0).Sub(transferAmount, big.NewInt(int64(nonce))) - } else { - actualTransferAmount = big.NewInt(0).Add(transferAmount, big.NewInt(int64(nonce))) - } - _, err := erc20SC.Transfer(shared.Auth, shared.To, actualTransferAmount) - require.NoError(b, err) -} diff --git a/test/benchmarks/sequencer/erc20-transfers/tx_sender.go b/test/benchmarks/sequencer/erc20-transfers/tx_sender.go new file mode 100644 index 0000000000..e88652d2ed --- /dev/null +++ b/test/benchmarks/sequencer/erc20-transfers/tx_sender.go @@ -0,0 +1,30 @@ +package erc20_transfers + +import ( + "math/big" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ( + mintAmount, _ = big.NewInt(0).SetString("1000000000000000000000", encoding.Base10) + transferAmount = big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Div(mintAmount, big.NewInt(shared.NumberOfTxs)), big.NewInt(90)), big.NewInt(100)) + erc20SC *ERC20.ERC20 +) + +func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) error { + log.Debugf("sending nonce: %d", nonce) + var actualTransferAmount *big.Int + if nonce%2 == 0 { + actualTransferAmount = big.NewInt(0).Sub(transferAmount, big.NewInt(int64(nonce))) + } else { + actualTransferAmount = big.NewInt(0).Add(transferAmount, big.NewInt(int64(nonce))) + } + _, err := erc20SC.Transfer(shared.Auth, shared.To, actualTransferAmount) + return err +} diff --git a/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go b/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go index 8f1affc6e4..90189069e3 100644 --- a/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go +++ b/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go @@ -2,66 +2,41 @@ package eth_transfers import ( "context" - "errors" "fmt" - "math/big" "net/http" "testing" "time" - "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/state" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/metrics" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/setup" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" - "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" ) -var ( - ethAmount, _ = big.NewInt(0).SetString("100000000000", encoding.Base10) -) - const ( - nTxs = 10 - gasLimit = 21000 - profilingEnabled = true + profilingEnabled = false ) func BenchmarkSequencerEthTransfersPoolProcess(b *testing.B) { ctx := context.Background() //defer func() { require.NoError(b, operations.Teardown()) }() opsman, client, pl, senderNonce, gasPrice := setup.Environment(ctx, b) - transactions.SendAndWait(b, senderNonce, client, gasPrice, pl, ctx, nTxs, runTxSender) + shared.Auth.GasPrice = gasPrice + err := transactions.SendAndWait(shared.Ctx, shared.Auth, senderNonce, client, pl.CountTransactionsByStatus, shared.NumberOfTxs, TxSender) + require.NoError(b, err) setup.BootstrapSequencer(b, opsman) var ( elapsed time.Duration prometheusResponse *http.Response - err error ) - b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", nTxs), func(b *testing.B) { - // Wait all txs to be selected by the sequencer - start := time.Now() - log.Debug("Wait for sequencer to select all txs from the pool") - err := operations.Poll(1*time.Second, shared.DefaultDeadline, func() (bool, error) { - selectedCount, err := pl.CountTransactionsByStatus(ctx, pool.TxStatusSelected) - if err != nil { - return false, err - } - - log.Debugf("amount of selected txs: %d", selectedCount) - done := selectedCount >= nTxs - return done, nil - }) + b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", shared.NumberOfTxs), func(b *testing.B) { + err, _ := transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) require.NoError(b, err) - elapsed = time.Since(start) prometheusResponse, err = metrics.FetchPrometheus() require.NoError(b, err) @@ -78,21 +53,6 @@ func BenchmarkSequencerEthTransfersPoolProcess(b *testing.B) { log.Errorf("failed to teardown: %s", err) } - metrics.CalculateAndPrint(prometheusResponse, profilingResult, elapsed, 0, 0, nTxs) + metrics.CalculateAndPrint(prometheusResponse, profilingResult, elapsed, 0, 0, shared.NumberOfTxs) fmt.Printf("%s\n", profilingResult) } - -func runTxSender(b *testing.B, l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) { - log.Debugf("sending nonce: %d", nonce) - tx := types.NewTransaction(nonce, shared.To, ethAmount, gasLimit, gasPrice, nil) - signedTx, err := shared.Auth.Signer(shared.Auth.From, tx) - require.NoError(b, err) - err = l2Client.SendTransaction(shared.Ctx, signedTx) - if errors.Is(err, state.ErrStateNotSynchronized) { - for errors.Is(err, state.ErrStateNotSynchronized) { - time.Sleep(5 * time.Second) - err = l2Client.SendTransaction(shared.Ctx, signedTx) - } - } - require.NoError(b, err) -} diff --git a/test/benchmarks/sequencer/eth-transfers/tx_sender.go b/test/benchmarks/sequencer/eth-transfers/tx_sender.go new file mode 100644 index 0000000000..a0b28c172b --- /dev/null +++ b/test/benchmarks/sequencer/eth-transfers/tx_sender.go @@ -0,0 +1,37 @@ +package eth_transfers + +import ( + "errors" + "math/big" + "time" + + "github.com/0xPolygonHermez/zkevm-node/encoding" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethclient" +) + +var ( + gasLimit = uint64(21000) + ethAmount, _ = big.NewInt(0).SetString("100000000000", encoding.Base10) +) + +func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) error { + log.Debugf("sending nonce: %d", nonce) + tx := types.NewTransaction(nonce, shared.To, ethAmount, gasLimit, gasPrice, nil) + signedTx, err := shared.Auth.Signer(shared.Auth.From, tx) + if err != nil { + return err + } + + err = l2Client.SendTransaction(shared.Ctx, signedTx) + if errors.Is(err, state.ErrStateNotSynchronized) { + for errors.Is(err, state.ErrStateNotSynchronized) { + time.Sleep(5 * time.Second) + err = l2Client.SendTransaction(shared.Ctx, signedTx) + } + } + return err +} diff --git a/test/benchmarks/sequencer/scripts/clients/init.go b/test/benchmarks/sequencer/scripts/clients/init.go new file mode 100644 index 0000000000..7abaec0d25 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/clients/init.go @@ -0,0 +1,76 @@ +package clients + +import ( + "context" + "math/big" + "strconv" + "strings" + + "github.com/0xPolygonHermez/zkevm-node/db" + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common" + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/ethclient" +) + +func Init() (context.Context, *pgpoolstorage.PostgresPoolStorage, *ethclient.Client, *bind.TransactOpts, uint64) { + ctx := common.Ctx + pl, err := pgpoolstorage.NewPostgresPoolStorage(db.Config{ + Name: common.PoolDbName, + User: common.PoolDbUser, + Password: common.PoolDbPass, + Host: common.PoolDbHost, + Port: common.PoolDbPort, + EnableLog: false, + MaxConns: 10, + }) + if err != nil { + panic(err) + } + + l2Client, err := ethclient.Dial(common.L2NetworkRPCURL) + if err != nil { + panic(err) + } + // PrivateKey is the private key of the sender + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(common.PrivateKey, "0x")) + if err != nil { + panic(err) + } + chainId, err := strconv.ParseUint(common.ChainId, 10, 64) + if err != nil { + panic(err) + } + // Auth is the auth of the sender + auth, err := bind.NewKeyedTransactorWithChainID(privateKey, new(big.Int).SetUint64(chainId)) + if err != nil { + panic(err) + } + + // Print Info before send + senderBalance, err := l2Client.BalanceAt(ctx, auth.From, nil) + if err != nil { + panic(err) + } + senderNonce, err := l2Client.PendingNonceAt(ctx, auth.From) + if err != nil { + panic(err) + } + + // Print Initial Stats + log.Infof("Receiver Addr: %v", shared.To.String()) + log.Infof("Sender Addr: %v", auth.From.String()) + log.Infof("Sender Balance: %v", senderBalance.String()) + log.Infof("Sender Nonce: %v", senderNonce) + + gasPrice, err := l2Client.SuggestGasPrice(ctx) + if err != nil { + panic(err) + } + auth.GasPrice = gasPrice + + return ctx, pl, l2Client, auth, senderNonce +} diff --git a/test/benchmarks/sequencer/scripts/common/constants.go b/test/benchmarks/sequencer/scripts/common/constants.go new file mode 100644 index 0000000000..dd1f06b60c --- /dev/null +++ b/test/benchmarks/sequencer/scripts/common/constants.go @@ -0,0 +1,22 @@ +package common + +import ( + "context" + "strconv" + + "github.com/0xPolygonHermez/zkevm-node/test/operations" + + "github.com/0xPolygonHermez/zkevm-node/test/testutils" +) + +var ( + Ctx = context.Background() + PoolDbName = testutils.GetEnv("POOL_DB_NAME", "pool_db") + PoolDbUser = testutils.GetEnv("POOL_DB_USER", "pool_user") + PoolDbPass = testutils.GetEnv("POOL_DB_PASS", "pool_password") + PoolDbHost = testutils.GetEnv("POOL_DB_HOST", "localhost") + PoolDbPort = testutils.GetEnv("POOL_DB_PORT", "5432") + L2NetworkRPCURL = testutils.GetEnv("L2_NETWORK_RPC_URL", "http://localhost:8545") + PrivateKey = testutils.GetEnv("PRIVATE_KEY", operations.DefaultSequencerPrivateKey) + ChainId = testutils.GetEnv("CHAIN_ID", strconv.FormatUint(operations.DefaultL2ChainID, 10)) +) diff --git a/test/benchmarks/sequencer/scripts/erc20-transfers/main.go b/test/benchmarks/sequencer/scripts/erc20-transfers/main.go new file mode 100644 index 0000000000..3484580913 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/erc20-transfers/main.go @@ -0,0 +1,45 @@ +package erc20_transfers + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" + erc20transfers "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/erc20-transfers" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/clients" +) + +func main() { + var ( + err error + elapsed time.Duration + ) + ctx, pl, l2Client, auth, senderNonce := clients.Init() + + // Send Txs + err = transactions.SendAndWait( + ctx, + auth, + senderNonce, + l2Client, + pl.CountTransactionsByStatus, + shared.NumberOfTxs, + erc20transfers.TxSender, + ) + if err != nil { + panic(err) + } + + // Wait for Txs to be selected + err, elapsed = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) + if err != nil { + panic(err) + } + + // Print results + log.Info("##########") + log.Info("# Result #") + log.Info("##########") + log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) +} diff --git a/test/benchmarks/sequencer/scripts/eth-transfers/main.go b/test/benchmarks/sequencer/scripts/eth-transfers/main.go new file mode 100644 index 0000000000..99d67ff24e --- /dev/null +++ b/test/benchmarks/sequencer/scripts/eth-transfers/main.go @@ -0,0 +1,46 @@ +package eth_transfers + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/clients" + + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" + ethtransfers "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/eth-transfers" +) + +func main() { + var ( + err error + elapsed time.Duration + ) + ctx, pl, l2Client, auth, senderNonce := clients.Init() + + // Send Txs + err = transactions.SendAndWait( + ctx, + auth, + senderNonce, + l2Client, + pl.CountTransactionsByStatus, + shared.NumberOfTxs, + ethtransfers.TxSender, + ) + if err != nil { + panic(err) + } + + // Wait for Txs to be selected + err, elapsed = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) + if err != nil { + panic(err) + } + + // Print results + log.Info("##########") + log.Info("# Result #") + log.Info("##########") + log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) +} From 2439dda1dd16c61d1996f48021a0ac948cad5775 Mon Sep 17 00:00:00 2001 From: Nikolay Nedkov Date: Tue, 21 Feb 2023 14:38:48 +0200 Subject: [PATCH 2/2] benchmark: adding benchmark test scripts Signed-off-by: Nikolay Nedkov --- state/pgstatestorage.go | 11 ++++ .../sequencer/common/metrics/metrics.go | 7 +-- .../common/{shared => params}/constants.go | 4 +- .../common/{shared => params}/variables.go | 6 +- .../sequencer/common/setup/setup.go | 30 ++++++---- .../common/transactions/transactions.go | 54 +++++++++++------ .../pool_processing_erc20_test.go | 38 ++++++------ .../sequencer/erc20-transfers/tx_sender.go | 27 +++++---- .../eth-transfers/pool_processing_eth_test.go | 28 ++++----- .../sequencer/eth-transfers/tx_sender.go | 23 +++++--- .../sequencer/scripts/common/constants.go | 22 ------- .../scripts/common/environment/constants.go | 33 +++++++++++ .../{clients => common/environment}/init.go | 59 +++++++++++++------ .../sequencer/scripts/common/results/print.go | 19 ++++++ .../sequencer/scripts/erc20-transfers/main.go | 35 ++++++----- .../sequencer/scripts/eth-transfers/main.go | 36 ++++++----- 16 files changed, 270 insertions(+), 162 deletions(-) rename test/benchmarks/sequencer/common/{shared => params}/constants.go (91%) rename test/benchmarks/sequencer/common/{shared => params}/variables.go (82%) delete mode 100644 test/benchmarks/sequencer/scripts/common/constants.go create mode 100644 test/benchmarks/sequencer/scripts/common/environment/constants.go rename test/benchmarks/sequencer/scripts/{clients => common/environment}/init.go (52%) create mode 100644 test/benchmarks/sequencer/scripts/common/results/print.go diff --git a/state/pgstatestorage.go b/state/pgstatestorage.go index 126c0bf78b..7097fc1e49 100644 --- a/state/pgstatestorage.go +++ b/state/pgstatestorage.go @@ -1105,6 +1105,17 @@ func (p *PostgresStorage) GetL2BlockByNumber(ctx context.Context, blockNumber ui return block, nil } +// GetLastL2BlockCreatedAt gets the timestamp of the last l2 block +func (p *PostgresStorage) GetLastL2BlockCreatedAt(ctx context.Context, dbTx pgx.Tx) (*time.Time, error) { + var createdAt time.Time + q := p.getExecQuerier(dbTx) + err := q.QueryRow(ctx, "SELECT created_at FROM state.l2block b order by b.block_num desc LIMIT 1").Scan(&createdAt) + if err != nil { + return nil, err + } + return &createdAt, nil +} + // GetTransactionByHash gets a transaction accordingly to the provided transaction hash func (p *PostgresStorage) GetTransactionByHash(ctx context.Context, transactionHash common.Hash, dbTx pgx.Tx) (*types.Transaction, error) { var encoded string diff --git a/test/benchmarks/sequencer/common/metrics/metrics.go b/test/benchmarks/sequencer/common/metrics/metrics.go index 484158afbe..4b825b8a9d 100644 --- a/test/benchmarks/sequencer/common/metrics/metrics.go +++ b/test/benchmarks/sequencer/common/metrics/metrics.go @@ -10,7 +10,7 @@ import ( metricsLib "github.com/0xPolygonHermez/zkevm-node/metrics" "github.com/0xPolygonHermez/zkevm-node/sequencer/metrics" metricsState "github.com/0xPolygonHermez/zkevm-node/state/metrics" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/testutils" ) @@ -35,7 +35,7 @@ func CalculateAndPrint(prometheusResp *http.Response, profilingResult string, el log.Info("##########") log.Info("# Result #") log.Info("##########") - log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) + log.Infof("Total time (including setup of environment and starting containers): %v", elapsed) if prometheusResp != nil { log.Info("######################") @@ -45,7 +45,6 @@ func CalculateAndPrint(prometheusResp *http.Response, profilingResult string, el actualExecutorTime := executorTime - executorTimeSub PrintPrometheus(actualTotalTime, actualExecutorTime, workerTime) log.Infof("[Transactions per second]: %v", float64(nTxs)/actualTotalTime) - } if profilingResult != "" { log.Info("#####################") @@ -93,7 +92,7 @@ func GetValues(metricsResponse *http.Response) (float64, float64, float64, error // FetchPrometheus fetches the prometheus metrics func FetchPrometheus() (*http.Response, error) { log.Infof("Fetching prometheus metrics ...") - return http.Get(fmt.Sprintf("http://localhost:%d%s", shared.PrometheusPort, metricsLib.Endpoint)) + return http.Get(fmt.Sprintf("http://localhost:%d%s", params.PrometheusPort, metricsLib.Endpoint)) } // FetchProfiling fetches the profiling metrics diff --git a/test/benchmarks/sequencer/common/shared/constants.go b/test/benchmarks/sequencer/common/params/constants.go similarity index 91% rename from test/benchmarks/sequencer/common/shared/constants.go rename to test/benchmarks/sequencer/common/params/constants.go index 3daecf058b..0cc1a0a919 100644 --- a/test/benchmarks/sequencer/common/shared/constants.go +++ b/test/benchmarks/sequencer/common/params/constants.go @@ -1,4 +1,4 @@ -package shared +package params import ( "time" @@ -12,5 +12,5 @@ const ( // PrometheusPort is the port where prometheus is running PrometheusPort = 9092 // NumberOfTxs is the number of transactions to send - NumberOfTxs = 1000 + NumberOfTxs = 100 ) diff --git a/test/benchmarks/sequencer/common/shared/variables.go b/test/benchmarks/sequencer/common/params/variables.go similarity index 82% rename from test/benchmarks/sequencer/common/shared/variables.go rename to test/benchmarks/sequencer/common/params/variables.go index 90513c84d1..9b12cbb930 100644 --- a/test/benchmarks/sequencer/common/shared/variables.go +++ b/test/benchmarks/sequencer/common/params/variables.go @@ -1,13 +1,11 @@ -package shared +package params import ( "context" - "math/big" "strings" "github.com/0xPolygonHermez/zkevm-node/test/dbutils" "github.com/0xPolygonHermez/zkevm-node/test/operations" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/crypto" ) @@ -29,6 +27,4 @@ var ( To = common.HexToAddress(ToAddress) // PrivateKey is the private key of the sender PrivateKey, _ = crypto.HexToECDSA(strings.TrimPrefix(SequencerPrivateKey, "0x")) - // Auth is the auth of the sender - Auth, _ = bind.NewKeyedTransactorWithChainID(PrivateKey, new(big.Int).SetUint64(ChainID)) ) diff --git a/test/benchmarks/sequencer/common/setup/setup.go b/test/benchmarks/sequencer/common/setup/setup.go index e6c0fcde1e..aed830aa9a 100644 --- a/test/benchmarks/sequencer/common/setup/setup.go +++ b/test/benchmarks/sequencer/common/setup/setup.go @@ -9,8 +9,9 @@ import ( "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" @@ -19,7 +20,7 @@ import ( const sleepDuration = 5 * time.Second // Environment sets up the environment for the benchmark -func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethclient.Client, *pool.Pool, uint64, *big.Int) { +func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethclient.Client, *pool.Pool, *bind.TransactOpts) { if testing.Short() { b.Skip() } @@ -27,8 +28,8 @@ func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethcl err := operations.Teardown() require.NoError(b, err) - shared.OpsCfg.State.MaxCumulativeGasUsed = shared.MaxCumulativeGasUsed - opsman, err := operations.NewManager(ctx, shared.OpsCfg) + params.OpsCfg.State.MaxCumulativeGasUsed = params.MaxCumulativeGasUsed + opsman, err := operations.NewManager(ctx, params.OpsCfg) require.NoError(b, err) err = Components(opsman) @@ -39,20 +40,20 @@ func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethcl auth, err := operations.GetAuth(operations.DefaultSequencerPrivateKey, operations.DefaultL2ChainID) require.NoError(b, err) - // Load common client + // Load params client client, err := ethclient.Dial(operations.DefaultL2NetworkURL) require.NoError(b, err) st := opsman.State() - s, err := pgpoolstorage.NewPostgresPoolStorage(shared.PoolDbConfig) + s, err := pgpoolstorage.NewPostgresPoolStorage(params.PoolDbConfig) require.NoError(b, err) config := pool.Config{ FreeClaimGasLimit: 1000000, //nolint:gomnd - DB: shared.PoolDbConfig, + DB: params.PoolDbConfig, } - pl := pool.NewPool(config, s, st, common.Address{}, shared.ChainID) + pl := pool.NewPool(config, s, st, common.Address{}, params.ChainID) // Print Info before send senderBalance, err := client.BalanceAt(ctx, auth.From, nil) @@ -61,7 +62,7 @@ func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethcl require.NoError(b, err) // Print Initial Stats - log.Infof("Receiver Addr: %v", shared.To.String()) + log.Infof("Receiver Addr: %v", params.To.String()) log.Infof("Sender Addr: %v", auth.From.String()) log.Infof("Sender Balance: %v", senderBalance.String()) log.Infof("Sender Nonce: %v", senderNonce) @@ -69,7 +70,16 @@ func Environment(ctx context.Context, b *testing.B) (*operations.Manager, *ethcl gasPrice, err := client.SuggestGasPrice(ctx) require.NoError(b, err) - return opsman, client, pl, senderNonce, gasPrice + // PrivateKey is the private key of the sender + // Auth is the auth of the sender + auth, err = bind.NewKeyedTransactorWithChainID(params.PrivateKey, new(big.Int).SetUint64(params.ChainID)) + if err != nil { + panic(err) + } + auth.GasPrice = gasPrice + auth.Nonce = new(big.Int).SetUint64(senderNonce) + + return opsman, client, pl, auth } // Components runs the network container, starts synchronizer and JSON-RPC components, and approves matic diff --git a/test/benchmarks/sequencer/common/transactions/transactions.go b/test/benchmarks/sequencer/common/transactions/transactions.go index c51dd41fde..a7b265ba7b 100644 --- a/test/benchmarks/sequencer/common/transactions/transactions.go +++ b/test/benchmarks/sequencer/common/transactions/transactions.go @@ -2,14 +2,15 @@ package transactions import ( "context" - "github.com/ethereum/go-ethereum/accounts/abi/bind" "math/big" + "strconv" "time" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/pool" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/ethclient" ) @@ -17,26 +18,25 @@ import ( func SendAndWait( ctx context.Context, auth *bind.TransactOpts, - senderNonce uint64, client *ethclient.Client, countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), nTxs int, - txSenderFunc func(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) error, + txSenderFunc func(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64, auth *bind.TransactOpts) error, ) error { auth.GasLimit = 2100000 log.Debugf("Sending %d txs ...", nTxs) - maxNonce := uint64(nTxs) + senderNonce + startingNonce := auth.Nonce.Uint64() + maxNonce := uint64(nTxs) + startingNonce - for nonce := senderNonce; nonce < maxNonce; nonce++ { - err := txSenderFunc(client, auth.GasPrice, nonce) + for nonce := startingNonce; nonce < maxNonce; nonce++ { + err := txSenderFunc(client, auth.GasPrice, nonce, auth) if err != nil { return err } } log.Debug("All txs were sent!") - log.Debug("Waiting pending transactions To be added in the pool ...") - err := operations.Poll(1*time.Second, shared.DefaultDeadline, func() (bool, error) { + err := operations.Poll(1*time.Second, params.DefaultDeadline, func() (bool, error) { // using a closure here To capture st and currentBatchNumber count, err := countByStatusFunc(ctx, pool.TxStatusPending) if err != nil { @@ -44,7 +44,7 @@ func SendAndWait( } log.Debugf("amount of pending txs: %d\n", count) - done := count == uint64(nTxs) + done := count == 0 return done, nil }) if err != nil { @@ -56,19 +56,37 @@ func SendAndWait( return nil } -func WaitStatusSelected(countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), nTxs uint64) (error, time.Duration) { - start := time.Now() +// WaitStatusSelected waits for a number of transactions to be marked as selected in the pool +func WaitStatusSelected(countByStatusFunc func(ctx context.Context, status pool.TxStatus) (uint64, error), initialCount uint64, nTxs uint64) error { log.Debug("Wait for sequencer to select all txs from the pool") - err := operations.Poll(200*time.Millisecond, shared.DefaultDeadline, func() (bool, error) { - selectedCount, err := countByStatusFunc(shared.Ctx, pool.TxStatusSelected) + pollingInterval := 1 * time.Second + + prevCount := uint64(0) + txsPerSecond := 0 + txsPerSecondAsStr := "N/A" + estimatedTimeToFinish := "N/A" + err := operations.Poll(pollingInterval, params.DefaultDeadline, func() (bool, error) { + selectedCount, err := countByStatusFunc(params.Ctx, pool.TxStatusSelected) if err != nil { return false, err } + currCount := selectedCount - initialCount + remainingTxs := nTxs - currCount + if prevCount > 0 { + txsPerSecond = int(currCount - prevCount) + if txsPerSecond == 0 { + estimatedTimeToFinish = "N/A" + } else { + estimatedTimeToFinish = (time.Duration(int(remainingTxs)/txsPerSecond) * time.Second).String() + } + txsPerSecondAsStr = strconv.Itoa(txsPerSecond) + } + log.Debugf("amount of selected txs: %d/%d, estimated txs per second: %s, time to finish: %s", selectedCount-initialCount, nTxs, txsPerSecondAsStr, estimatedTimeToFinish) + prevCount = currCount - log.Debugf("amount of selected txs: %d", selectedCount) - done := selectedCount >= nTxs + done := (int64(selectedCount) - int64(initialCount)) >= int64(nTxs) return done, nil }) - elapsed := time.Since(start) - return err, elapsed + + return err } diff --git a/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go b/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go index 69b590cef7..61a92b4d95 100644 --- a/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go +++ b/test/benchmarks/sequencer/erc20-transfers/pool_processing_erc20_test.go @@ -3,17 +3,20 @@ package erc20_transfers import ( "context" "fmt" + "math/big" "net/http" "testing" "time" "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/metrics" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/setup" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/stretchr/testify/require" @@ -25,20 +28,20 @@ const ( ) func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { - //defer func() { require.NoError(b, operations.Teardown()) }() - opsman, client, pl, senderNonce, gasPrice := setup.Environment(shared.Ctx, b) - + start := time.Now() + opsman, client, pl, auth := setup.Environment(params.Ctx, b) setup.BootstrapSequencer(b, opsman) startDeploySCTime := time.Now() - err := deployERC20Contract(b, client, shared.Ctx) + err := deployERC20Contract(b, client, params.Ctx, auth) require.NoError(b, err) deploySCElapsed := time.Since(startDeploySCTime) deploySCSequencerTime, deploySCExecutorOnlyTime, _, err := metrics.GetValues(nil) if err != nil { return } - shared.Auth.GasPrice = gasPrice - err = transactions.SendAndWait(shared.Ctx, shared.Auth, senderNonce, client, pl.CountTransactionsByStatus, shared.NumberOfTxs, TxSender) + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + require.NoError(b, err) + err = transactions.SendAndWait(params.Ctx, auth, client, pl.CountTransactionsByStatus, params.NumberOfTxs, TxSender) require.NoError(b, err) var ( @@ -46,10 +49,12 @@ func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { response *http.Response ) - b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", shared.NumberOfTxs), func(b *testing.B) { + b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", params.NumberOfTxs), func(b *testing.B) { // Wait all txs to be selected by the sequencer - err, _ := transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) require.NoError(b, err) + elapsed = time.Since(start) + log.Infof("Total elapsed time: %s", elapsed) response, err = metrics.FetchPrometheus() require.NoError(b, err) }) @@ -60,30 +65,27 @@ func BenchmarkSequencerERC20TransfersPoolProcess(b *testing.B) { require.NoError(b, err) } - err = operations.Teardown() - if err != nil { - log.Errorf("failed to teardown: %s", err) - } - - metrics.CalculateAndPrint(response, profilingResult, elapsed-deploySCElapsed, deploySCSequencerTime, deploySCExecutorOnlyTime, shared.NumberOfTxs) + metrics.CalculateAndPrint(response, profilingResult, elapsed-deploySCElapsed, deploySCSequencerTime, deploySCExecutorOnlyTime, params.NumberOfTxs) log.Infof("########################################") log.Infof("# Deploying ERC20 SC and Mint Tx took: #") log.Infof("########################################") metrics.PrintPrometheus(deploySCSequencerTime, deploySCExecutorOnlyTime, 0) } -func deployERC20Contract(b *testing.B, client *ethclient.Client, ctx context.Context) error { +func deployERC20Contract(b *testing.B, client *ethclient.Client, ctx context.Context, auth *bind.TransactOpts) error { var ( tx *types.Transaction err error ) log.Debugf("Sending TX to deploy ERC20 SC") - _, tx, erc20SC, err = ERC20.DeployERC20(shared.Auth, client, "Test Coin", "TCO") + _, tx, erc20SC, err = ERC20.DeployERC20(auth, client, "Test Coin", "TCO") require.NoError(b, err) err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) require.NoError(b, err) log.Debugf("Sending TX to do a ERC20 mint") - tx, err = erc20SC.Mint(shared.Auth, mintAmount) + auth.Nonce = big.NewInt(1) // for the mint tx + tx, err = erc20SC.Mint(auth, mintAmount) + auth.Nonce = big.NewInt(2) require.NoError(b, err) err = operations.WaitTxToBeMined(ctx, client, tx, txTimeout) require.NoError(b, err) diff --git a/test/benchmarks/sequencer/erc20-transfers/tx_sender.go b/test/benchmarks/sequencer/erc20-transfers/tx_sender.go index e88652d2ed..7900a0e616 100644 --- a/test/benchmarks/sequencer/erc20-transfers/tx_sender.go +++ b/test/benchmarks/sequencer/erc20-transfers/tx_sender.go @@ -4,27 +4,34 @@ import ( "math/big" "github.com/0xPolygonHermez/zkevm-node/encoding" - "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/0xPolygonHermez/zkevm-node/test/contracts/bin/ERC20" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/ethclient" ) var ( - mintAmount, _ = big.NewInt(0).SetString("1000000000000000000000", encoding.Base10) - transferAmount = big.NewInt(0).Div(big.NewInt(0).Mul(big.NewInt(0).Div(mintAmount, big.NewInt(shared.NumberOfTxs)), big.NewInt(90)), big.NewInt(100)) - erc20SC *ERC20.ERC20 + mintAmount, _ = big.NewInt(0).SetString("1000000000000000000000", encoding.Base10) + maxPercentage = 100 + percentageOfMintAmountToUse = 10 + transferAmount = big.NewInt(0).Div(big.NewInt(0).Mul( + big.NewInt(0).Div(mintAmount, big.NewInt(params.NumberOfTxs)), // 1/10 of the minted amount + big.NewInt(int64(percentageOfMintAmountToUse)), // 10% of the minted amount + ), big.NewInt(int64(maxPercentage))) // Divide by 100 to get the percentage + erc20SC *ERC20.ERC20 ) -func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) error { +// TxSender sends ERC20 transfer to the sequencer +func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64, auth *bind.TransactOpts) error { log.Debugf("sending nonce: %d", nonce) + auth.Nonce = new(big.Int).SetUint64(nonce) var actualTransferAmount *big.Int if nonce%2 == 0 { - actualTransferAmount = big.NewInt(0).Sub(transferAmount, big.NewInt(int64(nonce))) + actualTransferAmount = big.NewInt(0).Sub(transferAmount, auth.Nonce) } else { - actualTransferAmount = big.NewInt(0).Add(transferAmount, big.NewInt(int64(nonce))) + actualTransferAmount = big.NewInt(0).Add(transferAmount, auth.Nonce) } - _, err := erc20SC.Transfer(shared.Auth, shared.To, actualTransferAmount) + _, err := erc20SC.Transfer(auth, params.To, actualTransferAmount) return err } diff --git a/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go b/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go index 90189069e3..4eeacf6dc5 100644 --- a/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go +++ b/test/benchmarks/sequencer/eth-transfers/pool_processing_eth_test.go @@ -1,16 +1,15 @@ package eth_transfers import ( - "context" "fmt" "net/http" "testing" "time" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" - "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/pool" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/metrics" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/setup" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" "github.com/stretchr/testify/require" @@ -21,24 +20,26 @@ const ( ) func BenchmarkSequencerEthTransfersPoolProcess(b *testing.B) { - ctx := context.Background() + start := time.Now() //defer func() { require.NoError(b, operations.Teardown()) }() - opsman, client, pl, senderNonce, gasPrice := setup.Environment(ctx, b) - shared.Auth.GasPrice = gasPrice - err := transactions.SendAndWait(shared.Ctx, shared.Auth, senderNonce, client, pl.CountTransactionsByStatus, shared.NumberOfTxs, TxSender) + opsman, client, pl, auth := setup.Environment(params.Ctx, b) + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) require.NoError(b, err) setup.BootstrapSequencer(b, opsman) + err = transactions.SendAndWait(params.Ctx, auth, client, pl.CountTransactionsByStatus, params.NumberOfTxs, TxSender) + require.NoError(b, err) var ( elapsed time.Duration prometheusResponse *http.Response ) - b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", shared.NumberOfTxs), func(b *testing.B) { - err, _ := transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) + b.Run(fmt.Sprintf("sequencer_selecting_%d_txs", params.NumberOfTxs), func(b *testing.B) { + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) require.NoError(b, err) + elapsed = time.Since(start) + log.Infof("Total elapsed time: %s", elapsed) prometheusResponse, err = metrics.FetchPrometheus() - require.NoError(b, err) }) @@ -48,11 +49,6 @@ func BenchmarkSequencerEthTransfersPoolProcess(b *testing.B) { require.NoError(b, err) } - //err = operations.Teardown() - if err != nil { - log.Errorf("failed to teardown: %s", err) - } - - metrics.CalculateAndPrint(prometheusResponse, profilingResult, elapsed, 0, 0, shared.NumberOfTxs) + metrics.CalculateAndPrint(prometheusResponse, profilingResult, elapsed, 0, 0, params.NumberOfTxs) fmt.Printf("%s\n", profilingResult) } diff --git a/test/benchmarks/sequencer/eth-transfers/tx_sender.go b/test/benchmarks/sequencer/eth-transfers/tx_sender.go index a0b28c172b..762188d7e4 100644 --- a/test/benchmarks/sequencer/eth-transfers/tx_sender.go +++ b/test/benchmarks/sequencer/eth-transfers/tx_sender.go @@ -8,30 +8,35 @@ import ( "github.com/0xPolygonHermez/zkevm-node/encoding" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/state" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" + "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" ) var ( - gasLimit = uint64(21000) - ethAmount, _ = big.NewInt(0).SetString("100000000000", encoding.Base10) + gasLimit = 21000 + ethAmount, _ = big.NewInt(0).SetString("1", encoding.Base10) + sleepTime = 5 * time.Second ) -func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64) error { +// TxSender sends eth transfer to the sequencer +func TxSender(l2Client *ethclient.Client, gasPrice *big.Int, nonce uint64, auth *bind.TransactOpts) error { log.Debugf("sending nonce: %d", nonce) - tx := types.NewTransaction(nonce, shared.To, ethAmount, gasLimit, gasPrice, nil) - signedTx, err := shared.Auth.Signer(shared.Auth.From, tx) + auth.Nonce = big.NewInt(int64(nonce)) + tx := types.NewTransaction(nonce, params.To, ethAmount, uint64(gasLimit), gasPrice, nil) + signedTx, err := auth.Signer(auth.From, tx) if err != nil { return err } - err = l2Client.SendTransaction(shared.Ctx, signedTx) + err = l2Client.SendTransaction(params.Ctx, signedTx) if errors.Is(err, state.ErrStateNotSynchronized) { for errors.Is(err, state.ErrStateNotSynchronized) { - time.Sleep(5 * time.Second) - err = l2Client.SendTransaction(shared.Ctx, signedTx) + time.Sleep(sleepTime) + err = l2Client.SendTransaction(params.Ctx, signedTx) } } + return err } diff --git a/test/benchmarks/sequencer/scripts/common/constants.go b/test/benchmarks/sequencer/scripts/common/constants.go deleted file mode 100644 index dd1f06b60c..0000000000 --- a/test/benchmarks/sequencer/scripts/common/constants.go +++ /dev/null @@ -1,22 +0,0 @@ -package common - -import ( - "context" - "strconv" - - "github.com/0xPolygonHermez/zkevm-node/test/operations" - - "github.com/0xPolygonHermez/zkevm-node/test/testutils" -) - -var ( - Ctx = context.Background() - PoolDbName = testutils.GetEnv("POOL_DB_NAME", "pool_db") - PoolDbUser = testutils.GetEnv("POOL_DB_USER", "pool_user") - PoolDbPass = testutils.GetEnv("POOL_DB_PASS", "pool_password") - PoolDbHost = testutils.GetEnv("POOL_DB_HOST", "localhost") - PoolDbPort = testutils.GetEnv("POOL_DB_PORT", "5432") - L2NetworkRPCURL = testutils.GetEnv("L2_NETWORK_RPC_URL", "http://localhost:8545") - PrivateKey = testutils.GetEnv("PRIVATE_KEY", operations.DefaultSequencerPrivateKey) - ChainId = testutils.GetEnv("CHAIN_ID", strconv.FormatUint(operations.DefaultL2ChainID, 10)) -) diff --git a/test/benchmarks/sequencer/scripts/common/environment/constants.go b/test/benchmarks/sequencer/scripts/common/environment/constants.go new file mode 100644 index 0000000000..10f54a3d98 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/common/environment/constants.go @@ -0,0 +1,33 @@ +package environment + +import ( + "strconv" + + "github.com/0xPolygonHermez/zkevm-node/test/operations" + "github.com/0xPolygonHermez/zkevm-node/test/testutils" +) + +var ( + // IntBase is the base for the conversion of strings to integers + IntBase = 10 + // PrivateKey is the private key of the sequencer + PrivateKey = testutils.GetEnv("PRIVATE_KEY", operations.DefaultSequencerPrivateKey) + // L2ChainId is the chain id of the L2 network + L2ChainId = testutils.GetEnv("CHAIN_ID", strconv.FormatUint(operations.DefaultL2ChainID, IntBase)) + + l2NetworkRPCURL = testutils.GetEnv("L2_NETWORK_RPC_URL", operations.DefaultL2NetworkURL) + + // StateDB Credentials + stateDbName = testutils.GetEnv("STATE_DB_NAME", "state_db") + stateDbUser = testutils.GetEnv("STATE_DB_USER", "state_user") + stateDbPass = testutils.GetEnv("STATE_DB_PASS", "state_password") + stateDbHost = testutils.GetEnv("STATE_DB_HOST", "localhost") + stateDbPort = testutils.GetEnv("STATE_DB_PORT", "5432") + + // PoolDB Credentials + poolDbName = testutils.GetEnv("POOL_DB_NAME", "pool_db") + poolDbUser = testutils.GetEnv("POOL_DB_USER", "pool_user") + poolDbPass = testutils.GetEnv("POOL_DB_PASS", "pool_password") + poolDbHost = testutils.GetEnv("POOL_DB_HOST", "localhost") + poolDbPort = testutils.GetEnv("POOL_DB_PORT", "5433") +) diff --git a/test/benchmarks/sequencer/scripts/clients/init.go b/test/benchmarks/sequencer/scripts/common/environment/init.go similarity index 52% rename from test/benchmarks/sequencer/scripts/clients/init.go rename to test/benchmarks/sequencer/scripts/common/environment/init.go index 7abaec0d25..d043aeaea6 100644 --- a/test/benchmarks/sequencer/scripts/clients/init.go +++ b/test/benchmarks/sequencer/scripts/common/environment/init.go @@ -1,7 +1,8 @@ -package clients +package environment import ( "context" + "fmt" "math/big" "strconv" "strings" @@ -9,47 +10,56 @@ import ( "github.com/0xPolygonHermez/zkevm-node/db" "github.com/0xPolygonHermez/zkevm-node/log" "github.com/0xPolygonHermez/zkevm-node/pool/pgpoolstorage" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common" + "github.com/0xPolygonHermez/zkevm-node/state" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethclient" ) -func Init() (context.Context, *pgpoolstorage.PostgresPoolStorage, *ethclient.Client, *bind.TransactOpts, uint64) { - ctx := common.Ctx +var ( + maxConnections = 10 + bitSize = 64 +) + +// Init sets up the environment for the benchmark +func Init() (context.Context, *pgpoolstorage.PostgresPoolStorage, *state.PostgresStorage, *ethclient.Client, *bind.TransactOpts) { + ctx := context.Background() pl, err := pgpoolstorage.NewPostgresPoolStorage(db.Config{ - Name: common.PoolDbName, - User: common.PoolDbUser, - Password: common.PoolDbPass, - Host: common.PoolDbHost, - Port: common.PoolDbPort, + Name: poolDbName, + User: poolDbUser, + Password: poolDbPass, + Host: poolDbHost, + Port: poolDbPort, EnableLog: false, - MaxConns: 10, + MaxConns: maxConnections, }) if err != nil { panic(err) } - l2Client, err := ethclient.Dial(common.L2NetworkRPCURL) + l2Client, err := ethclient.Dial(l2NetworkRPCURL) + fmt.Println(l2Client.ChainID(ctx)) if err != nil { panic(err) } // PrivateKey is the private key of the sender - privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(common.PrivateKey, "0x")) + privateKey, err := crypto.HexToECDSA(strings.TrimPrefix(PrivateKey, "0x")) if err != nil { panic(err) } - chainId, err := strconv.ParseUint(common.ChainId, 10, 64) + chainId, err := strconv.ParseUint(L2ChainId, IntBase, bitSize) if err != nil { panic(err) } + log.Infof("L2ChainId: %d", chainId) // Auth is the auth of the sender auth, err := bind.NewKeyedTransactorWithChainID(privateKey, new(big.Int).SetUint64(chainId)) if err != nil { panic(err) } - + fmt.Printf("\nAuth(#): %#v", auth) + fmt.Printf("\nAuth(+): %+v", auth) // Print Info before send senderBalance, err := l2Client.BalanceAt(ctx, auth.From, nil) if err != nil { @@ -61,7 +71,7 @@ func Init() (context.Context, *pgpoolstorage.PostgresPoolStorage, *ethclient.Cli } // Print Initial Stats - log.Infof("Receiver Addr: %v", shared.To.String()) + log.Infof("Receiver Addr: %v", params.To.String()) log.Infof("Sender Addr: %v", auth.From.String()) log.Infof("Sender Balance: %v", senderBalance.String()) log.Infof("Sender Nonce: %v", senderNonce) @@ -71,6 +81,21 @@ func Init() (context.Context, *pgpoolstorage.PostgresPoolStorage, *ethclient.Cli panic(err) } auth.GasPrice = gasPrice + stateDbCfg := db.Config{ + User: stateDbUser, + Password: stateDbPass, + Name: stateDbName, + Host: stateDbHost, + Port: stateDbPort, + EnableLog: true, + MaxConns: maxConnections, + } + stateDb, err := db.NewSQLDB(stateDbCfg) + if err != nil { + panic(err) + } + stateStorage := state.NewPostgresStorage(stateDb) + auth.Nonce = new(big.Int).SetUint64(senderNonce) - return ctx, pl, l2Client, auth, senderNonce + return ctx, pl, stateStorage, l2Client, auth } diff --git a/test/benchmarks/sequencer/scripts/common/results/print.go b/test/benchmarks/sequencer/scripts/common/results/print.go new file mode 100644 index 0000000000..abee515213 --- /dev/null +++ b/test/benchmarks/sequencer/scripts/common/results/print.go @@ -0,0 +1,19 @@ +package results + +import ( + "time" + + "github.com/0xPolygonHermez/zkevm-node/log" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" +) + +// Print prints the results of the benchmark +func Print(elapsed time.Duration) { + // Print results + log.Info("##########") + log.Info("# Result #") + log.Info("##########") + log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) + log.Infof("Number of txs sent: %d", params.NumberOfTxs) + log.Infof("Txs per second: %f", float64(params.NumberOfTxs)/elapsed.Seconds()) +} diff --git a/test/benchmarks/sequencer/scripts/erc20-transfers/main.go b/test/benchmarks/sequencer/scripts/erc20-transfers/main.go index 3484580913..154e40c22f 100644 --- a/test/benchmarks/sequencer/scripts/erc20-transfers/main.go +++ b/test/benchmarks/sequencer/scripts/erc20-transfers/main.go @@ -1,45 +1,50 @@ -package erc20_transfers +package main import ( "time" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" erc20transfers "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/erc20-transfers" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/clients" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/environment" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/results" ) func main() { var ( - err error - elapsed time.Duration + err error ) - ctx, pl, l2Client, auth, senderNonce := clients.Init() + ctx, pl, state, l2Client, auth := environment.Init() + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + if err != nil { + panic(err) + } // Send Txs err = transactions.SendAndWait( ctx, auth, - senderNonce, l2Client, pl.CountTransactionsByStatus, - shared.NumberOfTxs, + params.NumberOfTxs, erc20transfers.TxSender, ) if err != nil { panic(err) } + start := time.Now() // Wait for Txs to be selected - err, elapsed = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) if err != nil { panic(err) } - // Print results - log.Info("##########") - log.Info("# Result #") - log.Info("##########") - log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) + lastL2BlockTimestamp, err := state.GetLastL2BlockCreatedAt(params.Ctx, nil) + if err != nil { + panic(err) + } + elapsed := lastL2BlockTimestamp.Sub(start) + results.Print(elapsed) } diff --git a/test/benchmarks/sequencer/scripts/eth-transfers/main.go b/test/benchmarks/sequencer/scripts/eth-transfers/main.go index 99d67ff24e..9e1e6fb0c5 100644 --- a/test/benchmarks/sequencer/scripts/eth-transfers/main.go +++ b/test/benchmarks/sequencer/scripts/eth-transfers/main.go @@ -1,46 +1,50 @@ -package eth_transfers +package main import ( "time" - "github.com/0xPolygonHermez/zkevm-node/log" - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/clients" - - "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/shared" + "github.com/0xPolygonHermez/zkevm-node/pool" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/params" "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/common/transactions" ethtransfers "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/eth-transfers" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/environment" + "github.com/0xPolygonHermez/zkevm-node/test/benchmarks/sequencer/scripts/common/results" ) func main() { var ( - err error - elapsed time.Duration + err error ) - ctx, pl, l2Client, auth, senderNonce := clients.Init() + ctx, pl, state, l2Client, auth := environment.Init() + initialCount, err := pl.CountTransactionsByStatus(params.Ctx, pool.TxStatusSelected) + if err != nil { + panic(err) + } // Send Txs err = transactions.SendAndWait( ctx, auth, - senderNonce, l2Client, pl.CountTransactionsByStatus, - shared.NumberOfTxs, + params.NumberOfTxs, ethtransfers.TxSender, ) if err != nil { panic(err) } + start := time.Now() // Wait for Txs to be selected - err, elapsed = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, shared.NumberOfTxs) + err = transactions.WaitStatusSelected(pl.CountTransactionsByStatus, initialCount, params.NumberOfTxs) if err != nil { panic(err) } - // Print results - log.Info("##########") - log.Info("# Result #") - log.Info("##########") - log.Infof("Total time took for the sequencer to select all txs from the pool: %v", elapsed) + lastL2BlockTimestamp, err := state.GetLastL2BlockCreatedAt(params.Ctx, nil) + if err != nil { + panic(err) + } + elapsed := lastL2BlockTimestamp.Sub(start) + results.Print(elapsed) }