diff --git a/app/app.go b/app/app.go index 7429271ad3..a2c1147196 100644 --- a/app/app.go +++ b/app/app.go @@ -964,8 +964,8 @@ func (app *App) ProcessTxConcurrent( ) { defer wg.Done() // Store the Channels in the Context Object for each transaction - ctx.WithTxBlockingChannels(getChannelsFromSignalMapping(txBlockingSignalsMap)) - ctx.WithTxCompletionChannels(getChannelsFromSignalMapping(txCompletionSignalingMap)) + ctx = ctx.WithTxBlockingChannels(getChannelsFromSignalMapping(txBlockingSignalsMap)) + ctx = ctx.WithTxCompletionChannels(getChannelsFromSignalMapping(txCompletionSignalingMap)) // Deliver the transaction and store the result in the channel resultChan <- ChannelResult{txIndex, app.DeliverTxWithResult(ctx, txBytes)} diff --git a/loadtest/config.json b/loadtest/config.json index d51806f496..d8673d83b0 100644 --- a/loadtest/config.json +++ b/loadtest/config.json @@ -14,9 +14,10 @@ "number_of_distinct_values": 20 }, "message_type_distribution": { - "limit_order_percentage": "0.8", - "market_order_percentage": "0.2" + "limit_order_percentage": "0.2", + "market_order_percentage": "0.8" }, + "message_type": "basic", "contract_distribution": [ { "contract_address": "sei1yw4xvtc43me9scqfr2jr2gzvcxd3a9y4eq7gaukreugw2yd2f8tsy4qgdm", diff --git a/loadtest/main.go b/loadtest/main.go index fab61cd31b..1759091eca 100644 --- a/loadtest/main.go +++ b/loadtest/main.go @@ -11,6 +11,10 @@ import ( "sync" "time" + cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types" + + banktypes "github.com/cosmos/cosmos-sdk/x/bank/types" + "github.com/cosmos/cosmos-sdk/client" "github.com/cosmos/cosmos-sdk/codec" "github.com/cosmos/cosmos-sdk/codec/types" @@ -37,6 +41,7 @@ type Config struct { ChainID string `json:"chain_id"` OrdersPerBlock uint64 `json:"orders_per_block"` Rounds uint64 `json:"rounds"` + MessageType string `json:"message_type"` PriceDistr NumericDistribution `json:"price_distribution"` QuantityDistr NumericDistribution `json:"quantity_distribution"` MsgTypeDistr MsgTypeDistribution `json:"message_type_distribution"` @@ -166,52 +171,13 @@ func run(config Config) { wgs = append(wgs, wg) for _, account := range activeAccounts { key := GetKey(uint64(account)) - var msg sdk.Msg - msgType := config.MsgTypeDistr.Sample() - orderPlacements := []*dextypes.Order{} - var orderType dextypes.OrderType - if msgType == "limit" { - orderType = dextypes.OrderType_LIMIT - } else { - orderType = dextypes.OrderType_MARKET - } - var direction dextypes.PositionDirection - if rand.Float64() < 0.5 { - direction = dextypes.PositionDirection_LONG - } else { - direction = dextypes.PositionDirection_SHORT - } - price := config.PriceDistr.Sample() - quantity := config.QuantityDistr.Sample() - contract := config.ContractDistr.Sample() - for j := 0; j < int(batchSize); j++ { - orderPlacements = append(orderPlacements, &dextypes.Order{ - Account: sdk.AccAddress(key.PubKey().Address()).String(), - ContractAddr: contract, - PositionDirection: direction, - Price: price.Quo(FromMili), - Quantity: quantity.Quo(FromMili), - PriceDenom: "SEI", - AssetDenom: "ATOM", - OrderType: orderType, - Data: VortexData, - }) - } - amount, err := sdk.ParseCoinsNormalized(fmt.Sprintf("%d%s", price.Mul(quantity).Ceil().RoundInt64(), "usei")) - if err != nil { - panic(err) - } - msg = &dextypes.MsgPlaceOrders{ - Creator: sdk.AccAddress(key.PubKey().Address()).String(), - Orders: orderPlacements, - ContractAddr: contract, - Funds: amount, - } - txBuilder := TestConfig.TxConfig.NewTxBuilder() + msg := generateMessage(config, key, batchSize) + txBuilder := TestConfig.TxConfig.NewTxBuilder() _ = txBuilder.SetMsgs(msg) seqDelta := uint64(i / 2) mode := typestx.BroadcastMode_BROADCAST_MODE_SYNC + // Note: There is a potential race condition here with seqnos // in which a later seqno is delievered before an earlier seqno // In practice, we haven't run into this issue so we'll leave this @@ -247,6 +213,65 @@ func run(config Config) { fmt.Printf("%s - Finished\n", time.Now().Format("2006-01-02T15:04:05")) } +func generateMessage(config Config, key cryptotypes.PrivKey, batchSize uint64) sdk.Msg { + var msg sdk.Msg + switch config.MessageType { + case "basic": + msg = &banktypes.MsgSend{ + FromAddress: sdk.AccAddress(key.PubKey().Address()).String(), + ToAddress: sdk.AccAddress(key.PubKey().Address()).String(), + Amount: sdk.NewCoins(sdk.Coin{ + Denom: "usei", + Amount: sdk.NewInt(1), + }), + } + case "dex": + msgType := config.MsgTypeDistr.Sample() + orderPlacements := []*dextypes.Order{} + var orderType dextypes.OrderType + if msgType == "limit" { + orderType = dextypes.OrderType_LIMIT + } else { + orderType = dextypes.OrderType_MARKET + } + var direction dextypes.PositionDirection + if rand.Float64() < 0.5 { + direction = dextypes.PositionDirection_LONG + } else { + direction = dextypes.PositionDirection_SHORT + } + price := config.PriceDistr.Sample() + quantity := config.QuantityDistr.Sample() + contract := config.ContractDistr.Sample() + for j := 0; j < int(batchSize); j++ { + orderPlacements = append(orderPlacements, &dextypes.Order{ + Account: sdk.AccAddress(key.PubKey().Address()).String(), + ContractAddr: contract, + PositionDirection: direction, + Price: price.Quo(FromMili), + Quantity: quantity.Quo(FromMili), + PriceDenom: "SEI", + AssetDenom: "ATOM", + OrderType: orderType, + Data: VortexData, + }) + } + amount, err := sdk.ParseCoinsNormalized(fmt.Sprintf("%d%s", price.Mul(quantity).Ceil().RoundInt64(), "usei")) + if err != nil { + panic(err) + } + msg = &dextypes.MsgPlaceOrders{ + Creator: sdk.AccAddress(key.PubKey().Address()).String(), + Orders: orderPlacements, + ContractAddr: contract, + Funds: amount, + } + default: + fmt.Printf("Unrecognized message type %s", config.MessageType) + } + return msg +} + func getLastHeight() int { out, err := exec.Command("curl", "http://localhost:26657/blockchain").Output() if err != nil { diff --git a/loadtest/scripts/metrics.py b/loadtest/scripts/metrics.py index b1f712752d..55074b6b30 100644 --- a/loadtest/scripts/metrics.py +++ b/loadtest/scripts/metrics.py @@ -1,3 +1,4 @@ +import json import requests import os from datetime import datetime @@ -33,22 +34,30 @@ def get_block_info(height): def get_metrics(): all_heights = get_all_heights() - print(all_heights) - if len(all_heights) == 1: + if len(all_heights) <= 2: print("Not enough number of blocks to obtain meaningful metrics with. Exiting..") return block_info_list = [] for height in all_heights: block_info_list.append(get_block_info(height)) - total_duration = block_info_list[-1]["timestamp"] - block_info_list[0]["timestamp"] - average_block_time = total_duration.total_seconds() / (len(block_info_list) - 1) - total_txs_num = sum([block["number_of_txs"] for block in block_info_list]) - average_txs_num = total_txs_num / len(block_info_list) + # Skip first and last block since it may have high deviation if we start it at the end of the block + skip_edge_blocks = block_info_list[1:-1] + total_duration = skip_edge_blocks[-1]["timestamp"] - skip_edge_blocks[0]["timestamp"] + average_block_time = total_duration.total_seconds() / (len(skip_edge_blocks) - 1) + total_txs_num = sum([block["number_of_txs"] for block in skip_edge_blocks]) + average_txs_num = total_txs_num / len(skip_edge_blocks) return { - "average_block_time": average_block_time, - "average_throughput_per_block": average_txs_num / average_block_time, - "number_of_full_blocks": len(block_info_list), - "total_txs_num": total_txs_num, + "Summary (excl. edge block)": { + "average_block_time": average_block_time, + "average_throughput_per_block": average_txs_num, + "average_throughput_per_sec": average_txs_num / average_block_time, + "number_of_full_blocks": len(skip_edge_blocks), + "total_txs_num": total_txs_num, + }, + "Detail (incl. edge blocks)": { + "blocks": all_heights, + "txs_per_block": [block["number_of_txs"] for block in block_info_list] + } } -print(get_metrics()) +print(json.dumps(get_metrics(), indent=4)) diff --git a/loadtest/tx.go b/loadtest/tx.go index f889c5c65c..6dced6c6c6 100644 --- a/loadtest/tx.go +++ b/loadtest/tx.go @@ -20,9 +20,9 @@ func SendTx( seqDelta uint64, mu *sync.Mutex, ) func() { - (*txBuilder).SetGasLimit(2000000) + (*txBuilder).SetGasLimit(200000000) (*txBuilder).SetFeeAmount([]sdk.Coin{ - sdk.NewCoin("usei", sdk.NewInt(100000)), + sdk.NewCoin("usei", sdk.NewInt(10000000)), }) SignTx(txBuilder, key, seqDelta) txBytes, _ := TestConfig.TxConfig.TxEncoder()((*txBuilder).GetTx())