-
Notifications
You must be signed in to change notification settings - Fork 4.1k
feat(tools): speedtest #25555
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
feat(tools): speedtest #25555
Changes from all commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
646f2b9
wip
technicallyty 6f77ca6
wip init
technicallyty 0326825
some changes
technicallyty 3ba733e
some additional customizations
technicallyty 22717f9
lint fix
technicallyty 48efc64
Merge branch 'main' into technicallyty/speedtest
technicallyty eb33f98
add example, fix variable name
technicallyty 411032d
bank speedtest and go module
technicallyty 200a206
Merge branch 'technicallyty/speedtest' of ssh://github.com/cosmos/cos…
technicallyty 24f7c75
lint all and integrate speedtest to simd
technicallyty 3403d48
ok dont need go mod actually
technicallyty 4ad4386
add speedtest cmd code
technicallyty a0144e6
Merge branch 'main' into technicallyty/speedtest
aljo242 161fad0
fixes
technicallyty 2aec58e
Merge branch 'technicallyty/speedtest' of ssh://github.com/cosmos/cos…
technicallyty 3e148dc
ordering
technicallyty 86fdc72
Merge branch 'main' into technicallyty/speedtest
aljo242 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| package cmd | ||
|
|
||
| import ( | ||
| "math/rand" | ||
| "os" | ||
| "time" | ||
|
|
||
| dbm "github.com/cosmos/cosmos-db" | ||
| "github.com/spf13/cobra" | ||
|
|
||
| "cosmossdk.io/log" | ||
| "cosmossdk.io/simapp" | ||
|
|
||
| "github.com/cosmos/cosmos-sdk/baseapp" | ||
| "github.com/cosmos/cosmos-sdk/crypto/keys/secp256k1" | ||
| cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" | ||
| simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" | ||
| "github.com/cosmos/cosmos-sdk/tools/speedtest" | ||
| sdk "github.com/cosmos/cosmos-sdk/types" | ||
| authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
| banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
| ) | ||
|
|
||
| var r = rand.New(rand.NewSource(time.Now().UnixNano())) | ||
|
|
||
| func NewBankSpeedTest() *cobra.Command { | ||
| dir, err := os.MkdirTemp("", "bankspeedtest-*") | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| db, err := dbm.NewDB("app", dbm.PebbleDBBackend, dir) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| chainID := "foo" | ||
| app := simapp.NewSimApp(log.NewNopLogger(), db, nil, true, simtestutil.NewAppOptionsWithFlagHome(dir), baseapp.SetChainID(chainID)) | ||
| gen := generator{ | ||
| app: app, | ||
| accounts: make([]accountInfo, 0), | ||
| } | ||
| cmd := speedtest.NewCmd(gen.createAccount, gen.generateTx, app, app.AppCodec(), app.DefaultGenesis(), chainID) | ||
| cmd.PostRunE = func(_ *cobra.Command, _ []string) error { | ||
| return os.RemoveAll(dir) | ||
| } | ||
| return cmd | ||
| } | ||
|
|
||
| type generator struct { | ||
| app *simapp.SimApp | ||
| accounts []accountInfo | ||
| } | ||
|
|
||
| type accountInfo struct { | ||
| privKey cryptotypes.PrivKey | ||
| address sdk.AccAddress | ||
| accNum uint64 | ||
| seqNum uint64 | ||
| } | ||
|
|
||
| func (g *generator) createAccount() (*authtypes.BaseAccount, sdk.Coins) { | ||
| privKey := secp256k1.GenPrivKey() | ||
| addr := sdk.AccAddress(privKey.PubKey().Address()) | ||
| accNum := len(g.accounts) | ||
| baseAcc := authtypes.NewBaseAccount(addr, privKey.PubKey(), uint64(accNum), 0) | ||
|
|
||
| g.accounts = append(g.accounts, accountInfo{ | ||
| privKey: privKey, | ||
| address: addr, | ||
| accNum: uint64(accNum), | ||
| seqNum: 0, | ||
| }) | ||
|
|
||
| return baseAcc, sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1_000_000_000)) | ||
| } | ||
|
|
||
| func (g *generator) generateTx() []byte { | ||
| senderIdx := r.Intn(len(g.accounts)) | ||
| recipientIdx := (senderIdx + 1 + r.Intn(len(g.accounts)-1)) % len(g.accounts) | ||
| sender := g.accounts[senderIdx] | ||
| recipient := g.accounts[recipientIdx] | ||
| sendAmount := sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 1)) | ||
| msg := banktypes.NewMsgSend(sender.address, recipient.address, sendAmount) | ||
| txConfig := g.app.TxConfig() | ||
| // Build and sign transaction | ||
| tx, err := simtestutil.GenSignedMockTx( | ||
| r, | ||
| txConfig, | ||
| []sdk.Msg{msg}, | ||
| sdk.NewCoins(sdk.NewInt64Coin(sdk.DefaultBondDenom, 0)), | ||
| simtestutil.DefaultGenTxGas, | ||
| g.app.ChainID(), | ||
| []uint64{sender.accNum}, | ||
| []uint64{sender.seqNum}, | ||
| sender.privKey, | ||
| ) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| txBytes, err := txConfig.TxEncoder()(tx) | ||
| if err != nil { | ||
| panic(err) | ||
| } | ||
| g.accounts[senderIdx].seqNum++ | ||
| return txBytes | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,167 @@ | ||
| package speedtest | ||
|
|
||
| import ( | ||
| "encoding/json" | ||
| "fmt" | ||
| "math" | ||
| "time" | ||
|
|
||
| "github.com/cometbft/cometbft/abci/types" | ||
| cmtjson "github.com/cometbft/cometbft/libs/json" | ||
| "github.com/spf13/cobra" | ||
|
|
||
| "github.com/cosmos/cosmos-sdk/codec" | ||
| servertypes "github.com/cosmos/cosmos-sdk/server/types" | ||
| simtestutil "github.com/cosmos/cosmos-sdk/testutil/sims" | ||
| sdk "github.com/cosmos/cosmos-sdk/types" | ||
| authtypes "github.com/cosmos/cosmos-sdk/x/auth/types" | ||
| banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" | ||
| ) | ||
|
|
||
| type AccountCreator func() (*authtypes.BaseAccount, sdk.Coins) | ||
|
|
||
| type GenerateTx func() []byte | ||
|
|
||
| var ( | ||
| numAccounts = 10_000 | ||
| numTxsPerBlock = 4_000 | ||
| numBlocksToRun = 100 | ||
| blockMaxGas = math.MaxInt64 | ||
| blockMaxBytes = math.MaxInt64 | ||
| verifyTxs = false | ||
| ) | ||
|
|
||
| // NewCmd returns a command that will run an execution test on your application. | ||
| // Balances and accounts are automatically added to the chain's state via AccountCreator. | ||
| func NewCmd( | ||
| createAccount AccountCreator, | ||
| generateTx GenerateTx, | ||
| app servertypes.ABCI, | ||
| cdc codec.Codec, | ||
| genState map[string]json.RawMessage, | ||
| chainID string, | ||
| ) *cobra.Command { | ||
| cmd := &cobra.Command{ | ||
| Use: "speedtest", | ||
| Short: "execution speedtest", | ||
| Long: "speedtest is a tool for measuring raw execution TPS of your application", | ||
| Example: "speedtest --accounts 20000 --txs 2000 --blocks 10 --block-max-gas 1000000000 --block-max-bytes 1000000000 --verify-txs", | ||
| RunE: func(cmd *cobra.Command, args []string) error { | ||
| accounts := make([]simtestutil.GenesisAccount, 0, numAccounts) | ||
| balances := make([]banktypes.Balance, 0, numAccounts) | ||
| for range numAccounts { | ||
| account, balance := createAccount() | ||
| genesisAcc := simtestutil.GenesisAccount{ | ||
| GenesisAccount: account, | ||
| Coins: balance, | ||
| } | ||
| accounts = append(accounts, genesisAcc) | ||
| balances = append(balances, banktypes.Balance{ | ||
| Address: account.Address, | ||
| Coins: balance, | ||
| }) | ||
| } | ||
|
|
||
| vals, err := simtestutil.CreateRandomValidatorSet() | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| genAccs := make([]authtypes.GenesisAccount, 0, len(accounts)) | ||
| for _, acc := range accounts { | ||
| genAccs = append(genAccs, acc.GenesisAccount) | ||
| } | ||
| genesisState, err := simtestutil.GenesisStateWithValSet(cdc, genState, vals, genAccs, balances...) | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| // init chain must be called to stop deliverState from being nil | ||
| stateBytes, err := cmtjson.MarshalIndent(genesisState, "", " ") | ||
| if err != nil { | ||
| return err | ||
| } | ||
|
|
||
| cp := simtestutil.DefaultConsensusParams | ||
| cp.Block.MaxGas = int64(blockMaxGas) | ||
| cp.Block.MaxBytes = int64(blockMaxBytes) | ||
| _, err = app.InitChain(&types.RequestInitChain{ | ||
| ChainId: chainID, | ||
| Validators: []types.ValidatorUpdate{}, | ||
| ConsensusParams: cp, | ||
| AppStateBytes: stateBytes, | ||
| }) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to InitChain: %w", err) | ||
| } | ||
|
|
||
| // commit genesis changes | ||
| _, err = app.FinalizeBlock(&types.RequestFinalizeBlock{ | ||
| Height: 1, | ||
| NextValidatorsHash: vals.Hash(), | ||
| }) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to finalize genesis block: %w", err) | ||
| } | ||
|
|
||
| blocks := make([][][]byte, 0, numBlocksToRun) | ||
| for range numBlocksToRun { | ||
| block := make([][]byte, 0, numBlocksToRun) | ||
| for range numTxsPerBlock { | ||
| tx := generateTx() | ||
| block = append(block, tx) | ||
| } | ||
| blocks = append(blocks, block) | ||
| } | ||
|
|
||
| elapsed, err := runBlocks(blocks, app, vals.Proposer.Address, verifyTxs) | ||
| if err != nil { | ||
| return fmt.Errorf("failed to run blocks: %w", err) | ||
| } | ||
|
|
||
| cmd.Printf("Finished %d blocks in %s\n", numBlocksToRun, elapsed) | ||
| numTxs := numBlocksToRun * numTxsPerBlock | ||
| tps := float64(numTxs) / elapsed.Seconds() | ||
|
||
| cmd.Printf("TPS: %f", tps) | ||
|
|
||
| return nil | ||
| }, | ||
| } | ||
| cmd.Flags().IntVar(&numAccounts, "accounts", numAccounts, "number of accounts") | ||
| cmd.Flags().IntVar(&numTxsPerBlock, "txs", numTxsPerBlock, "number of txs") | ||
| cmd.Flags().IntVar(&numBlocksToRun, "blocks", numBlocksToRun, "number of blocks") | ||
| cmd.Flags().BoolVar(&verifyTxs, "verify-txs", verifyTxs, "verify txs passed. this will loop over all tx results and ensure the code == 0.") | ||
| cmd.Flags().IntVar(&blockMaxGas, "block-max-gas", blockMaxGas, "block max gas") | ||
| cmd.Flags().IntVar(&blockMaxBytes, "block-max-bytes", blockMaxBytes, "block max bytes") | ||
| return cmd | ||
| } | ||
|
|
||
| func runBlocks(blocks [][][]byte, app servertypes.ABCI, proposer []byte, verify bool) (time.Duration, error) { | ||
| start := time.Now() | ||
|
||
| height := int64(1) | ||
| for blockNum, txs := range blocks { | ||
| res, err := app.FinalizeBlock(&types.RequestFinalizeBlock{ | ||
| Height: height, | ||
| Txs: txs, | ||
| Time: time.Now(), | ||
|
||
| ProposerAddress: proposer, | ||
| }) | ||
| if err != nil { | ||
| return 0, fmt.Errorf("failed to finalize block #%d: %w", blockNum, err) | ||
| } | ||
| if verify { | ||
| for _, result := range res.TxResults { | ||
| if result.Code != 0 { | ||
| return 0, fmt.Errorf("tx failed in block %d: code=%d codespace=%s", blockNum, result.Code, result.Codespace) | ||
| } | ||
| } | ||
| } | ||
| _, err = app.Commit() | ||
| if err != nil { | ||
| return 0, fmt.Errorf("failed to commit block #%d: %w", blockNum, err) | ||
| } | ||
| height++ | ||
| } | ||
| end := time.Since(start) | ||
| return end, nil | ||
| } | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.