Merge PR #1332: benchmarks: Add benchmark for block time to bank module
* benchmarks: Add benchmark folder, and single benchmark for block time * Move benchmark into module * Fix merge conflict errors * Fix spelling * Add instructions to run benchmark * Update auth_app_test.go
This commit is contained in:
parent
3dc2387124
commit
49f421db19
|
@ -29,6 +29,8 @@ FEATURES
|
|||
* Supported proposal types: just binary (pass/fail) TextProposals for now
|
||||
* Proposals need deposits to be votable; deposits are burned if proposal fails
|
||||
* Delegators delegate votes to validator by default but can override (for their stake)
|
||||
* Add benchmarks for signing and delivering a block with a single bank transaction
|
||||
* Run with `cd x/bank && go test --bench=.`
|
||||
* [tools] make get_tools installs tendermint's linter, and gometalinter
|
||||
* [tools] Switch gometalinter to the stable version
|
||||
* [tools] Add checking for misspellings and for incorrectly formatted files in circle CI
|
||||
|
|
|
@ -3,7 +3,6 @@ package baseapp
|
|||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
|
@ -20,6 +19,7 @@ import (
|
|||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/wire"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
)
|
||||
|
||||
func defaultLogger() log.Logger {
|
||||
|
|
|
@ -3,14 +3,38 @@ package mock
|
|||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
crypto "github.com/tendermint/go-crypto"
|
||||
)
|
||||
|
||||
// A mock transaction that has a validation which can fail.
|
||||
type testMsg struct {
|
||||
signers []sdk.Address
|
||||
positiveNum int64
|
||||
}
|
||||
|
||||
// TODO: Clean this up, make it public
|
||||
const msgType = "testMsg"
|
||||
|
||||
func (tx testMsg) Type() string { return msgType }
|
||||
func (tx testMsg) GetMsg() sdk.Msg { return tx }
|
||||
func (tx testMsg) GetMemo() string { return "" }
|
||||
func (tx testMsg) GetSignBytes() []byte { return nil }
|
||||
func (tx testMsg) GetSigners() []sdk.Address { return tx.signers }
|
||||
func (tx testMsg) GetSignatures() []auth.StdSignature { return nil }
|
||||
func (tx testMsg) ValidateBasic() sdk.Error {
|
||||
if tx.positiveNum >= 0 {
|
||||
return nil
|
||||
}
|
||||
return sdk.ErrTxDecode("positiveNum should be a non-negative integer.")
|
||||
}
|
||||
|
||||
// test auth module messages
|
||||
|
||||
var (
|
||||
|
@ -20,19 +44,50 @@ var (
|
|||
addr2 = priv2.PubKey().Address()
|
||||
|
||||
coins = sdk.Coins{sdk.NewCoin("foocoin", 10)}
|
||||
sendMsg1 = bank.MsgSend{
|
||||
Inputs: []bank.Input{bank.NewInput(addr1, coins)},
|
||||
Outputs: []bank.Output{bank.NewOutput(addr2, coins)},
|
||||
}
|
||||
testMsg1 = testMsg{signers: []sdk.Address{addr1}, positiveNum: 1}
|
||||
)
|
||||
|
||||
// initialize the mock application for this module
|
||||
func getMockApp(t *testing.T) *App {
|
||||
mapp := NewApp()
|
||||
|
||||
coinKeeper := bank.NewKeeper(mapp.AccountMapper)
|
||||
mapp.Router().AddRoute("bank", bank.NewHandler(coinKeeper))
|
||||
|
||||
mapp.Router().AddRoute(msgType, func(ctx sdk.Context, msg sdk.Msg) (res sdk.Result) { return })
|
||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{}))
|
||||
return mapp
|
||||
}
|
||||
|
||||
func TestMsgPrivKeys(t *testing.T) {
|
||||
mapp := getMockApp(t)
|
||||
mapp.Cdc.RegisterConcrete(testMsg{}, "mock/testMsg", nil)
|
||||
|
||||
// Construct some genesis bytes to reflect basecoin/types/AppAccount
|
||||
// Give 77 foocoin to the first key
|
||||
coins := sdk.Coins{sdk.NewCoin("foocoin", 77)}
|
||||
acc1 := &auth.BaseAccount{
|
||||
Address: addr1,
|
||||
Coins: coins,
|
||||
}
|
||||
accs := []auth.Account{acc1}
|
||||
|
||||
// Construct genesis state
|
||||
SetGenesis(mapp, accs)
|
||||
|
||||
// A checkTx context (true)
|
||||
ctxCheck := mapp.BaseApp.NewContext(true, abci.Header{})
|
||||
res1 := mapp.AccountMapper.GetAccount(ctxCheck, addr1)
|
||||
assert.Equal(t, acc1, res1.(*auth.BaseAccount))
|
||||
|
||||
// Run a CheckDeliver
|
||||
SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{testMsg1}, []int64{0}, []int64{0}, true, priv1)
|
||||
|
||||
// signing a SendMsg with the wrong privKey should be an auth error
|
||||
mapp.BeginBlock(abci.RequestBeginBlock{})
|
||||
tx := GenTx([]sdk.Msg{testMsg1}, []int64{0}, []int64{1}, priv2)
|
||||
res := mapp.Deliver(tx)
|
||||
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeUnauthorized), res.Code, res.Log)
|
||||
|
||||
// resigning the tx with the correct priv key should still work
|
||||
res = SignCheckDeliver(t, mapp.BaseApp, []sdk.Msg{testMsg1}, []int64{0}, []int64{1}, true, priv1)
|
||||
|
||||
assert.Equal(t, sdk.ToABCICode(sdk.CodespaceRoot, sdk.CodeOK), res.Code, res.Log)
|
||||
}
|
||||
|
|
|
@ -54,6 +54,23 @@ func GenTx(msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyE
|
|||
return auth.NewStdTx(msgs, fee, sigs, memo)
|
||||
}
|
||||
|
||||
// generate a set of signed transactions a msg, that differ only by having the
|
||||
// sequence numbers incremented between every transaction.
|
||||
func GenSequenceOfTxs(msgs []sdk.Msg, accnums []int64, initSeqNums []int64, numToGenerate int, priv ...crypto.PrivKeyEd25519) []auth.StdTx {
|
||||
txs := make([]auth.StdTx, numToGenerate, numToGenerate)
|
||||
for i := 0; i < numToGenerate; i++ {
|
||||
txs[i] = GenTx(msgs, accnums, initSeqNums, priv...)
|
||||
incrementAllSequenceNumbers(initSeqNums)
|
||||
}
|
||||
return txs
|
||||
}
|
||||
|
||||
func incrementAllSequenceNumbers(initSeqNums []int64) {
|
||||
for i := 0; i < len(initSeqNums); i++ {
|
||||
initSeqNums[i]++
|
||||
}
|
||||
}
|
||||
|
||||
// check a transaction result
|
||||
func SignCheck(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, priv ...crypto.PrivKeyEd25519) sdk.Result {
|
||||
tx := GenTx(msgs, accnums, seq, priv...)
|
||||
|
@ -62,7 +79,7 @@ func SignCheck(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int
|
|||
}
|
||||
|
||||
// simulate a block
|
||||
func SignCheckDeliver(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) {
|
||||
func SignCheckDeliver(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnums []int64, seq []int64, expPass bool, priv ...crypto.PrivKeyEd25519) sdk.Result {
|
||||
|
||||
// Sign the tx
|
||||
tx := GenTx(msgs, accnums, seq, priv...)
|
||||
|
@ -86,4 +103,5 @@ func SignCheckDeliver(t *testing.T, app *baseapp.BaseApp, msgs []sdk.Msg, accnum
|
|||
app.EndBlock(abci.RequestEndBlock{})
|
||||
|
||||
app.Commit()
|
||||
return res
|
||||
}
|
||||
|
|
|
@ -77,14 +77,22 @@ var (
|
|||
|
||||
// initialize the mock application for this module
|
||||
func getMockApp(t *testing.T) *mock.App {
|
||||
mapp, err := getBenchmarkMockApp()
|
||||
require.NoError(t, err)
|
||||
return mapp
|
||||
}
|
||||
|
||||
// getBenchmarkMockApp initializes a mock application for this module, for purposes of benchmarking
|
||||
// Any long term API support commitments do not apply to this function.
|
||||
func getBenchmarkMockApp() (*mock.App, error) {
|
||||
mapp := mock.NewApp()
|
||||
|
||||
RegisterWire(mapp.Cdc)
|
||||
coinKeeper := NewKeeper(mapp.AccountMapper)
|
||||
mapp.Router().AddRoute("bank", NewHandler(coinKeeper))
|
||||
|
||||
require.NoError(t, mapp.CompleteSetup([]*sdk.KVStoreKey{}))
|
||||
return mapp
|
||||
err := mapp.CompleteSetup([]*sdk.KVStoreKey{})
|
||||
return mapp, err
|
||||
}
|
||||
|
||||
func TestMsgSendWithAccounts(t *testing.T) {
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
package bank
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth/mock"
|
||||
|
||||
abci "github.com/tendermint/abci/types"
|
||||
)
|
||||
|
||||
func BenchmarkOneBankSendTxPerBlock(b *testing.B) {
|
||||
benchmarkApp, _ := getBenchmarkMockApp()
|
||||
|
||||
// Add an account at genesis
|
||||
acc := &auth.BaseAccount{
|
||||
Address: addr1,
|
||||
// Some value conceivably higher than the benchmarks would ever go
|
||||
Coins: sdk.Coins{sdk.NewCoin("foocoin", 100000000000)},
|
||||
}
|
||||
accs := []auth.Account{acc}
|
||||
|
||||
// Construct genesis state
|
||||
mock.SetGenesis(benchmarkApp, accs)
|
||||
// Precompute all txs
|
||||
txs := mock.GenSequenceOfTxs([]sdk.Msg{sendMsg1}, []int64{0}, []int64{int64(0)}, b.N, priv1)
|
||||
b.ResetTimer()
|
||||
// Run this with a profiler, so its easy to distinguish what time comes from
|
||||
// Committing, and what time comes from Check/Deliver Tx.
|
||||
for i := 0; i < b.N; i++ {
|
||||
benchmarkApp.BeginBlock(abci.RequestBeginBlock{})
|
||||
x := benchmarkApp.Check(txs[i])
|
||||
if !x.IsOK() {
|
||||
panic("something is broken in checking transaction")
|
||||
}
|
||||
benchmarkApp.Deliver(txs[i])
|
||||
benchmarkApp.EndBlock(abci.RequestEndBlock{})
|
||||
benchmarkApp.Commit()
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue