gecko/vms/spchainvm/vm_benchmark_test.go

343 lines
7.6 KiB
Go

package spchainvm
import (
"testing"
"github.com/ava-labs/gecko/database/memdb"
"github.com/ava-labs/gecko/ids"
"github.com/ava-labs/gecko/snow"
"github.com/ava-labs/gecko/snow/consensus/snowman"
"github.com/ava-labs/gecko/snow/engine/common"
)
func genGenesisState(numBlocks, numTxsPerBlock int, b *testing.B) ([]byte, []*Block) {
ctx := snow.DefaultContextTest()
builder := Builder{
NetworkID: ctx.NetworkID,
ChainID: ctx.ChainID,
}
genesisBlock, err := builder.NewBlock(ids.Empty, nil)
if err != nil {
b.Fatal(err)
}
blocks := genBlocks(
/*numBlocks=*/ numBlocks,
/*numTxsPerBlock=*/ numTxsPerBlock,
/*initialParent=*/ genesisBlock.ID(),
/*testing=*/ b,
)
genesisAccounts := []Account{}
for _, block := range blocks {
for _, tx := range block.txs {
genesisAccounts = append(
genesisAccounts,
Account{
id: tx.Key(ctx).Address(),
nonce: tx.nonce - 1,
balance: tx.amount,
},
)
}
}
codec := Codec{}
genesisData, err := codec.MarshalGenesis(genesisAccounts)
if err != nil {
b.Fatal(err)
}
return genesisData, blocks
}
func genGenesisStateBytes(numBlocks, numTxsPerBlock int, b *testing.B) ([]byte, [][]byte) {
genesisData, blocks := genGenesisState(numBlocks, numTxsPerBlock, b)
blockBytes := make([][]byte, numBlocks)
for i, block := range blocks {
blockBytes[i] = block.Bytes()
}
return genesisData, blockBytes
}
// BenchmarkParseBlock runs the benchmark of parsing blocks
func BenchmarkParseBlock(b *testing.B) {
b.StopTimer()
b.ResetTimer()
ctx := snow.DefaultContextTest()
genesisBytes, blocks := genGenesisStateBytes(
/*numBlocks=*/ 1,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
vm := &VM{}
vm.Initialize(
/*ctx=*/ ctx,
/*db=*/ memdb.New(),
/*genesis=*/ genesisBytes,
/*engineChan=*/ make(chan common.Message, 1),
/*fxs=*/ nil,
)
for n := 0; n < b.N; n++ {
for _, blockBytes := range blocks {
vm.state.block.Flush()
b.StartTimer()
if _, err := vm.ParseBlock(blockBytes); err != nil {
b.Fatal(err)
}
b.StopTimer()
}
}
}
// BenchmarkParseAndVerify runs the benchmark of parsing blocks and verifying them
func BenchmarkParseAndVerify(b *testing.B) {
b.StopTimer()
b.ResetTimer()
genesisBytes, blocks := genGenesisStateBytes(
/*numBlocks=*/ 1,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
for n := 0; n < b.N; n++ {
vm := &VM{}
vm.Initialize(
/*ctx=*/ snow.DefaultContextTest(),
/*db=*/ memdb.New(),
/*genesis=*/ genesisBytes,
/*engineChan=*/ make(chan common.Message, 1),
/*fxs=*/ nil,
)
b.StartTimer()
for _, blockBytes := range blocks {
blk, err := vm.ParseBlock(blockBytes)
if err != nil {
b.Fatal(err)
}
if err := blk.Verify(); err != nil {
b.Fatal(err)
}
}
b.StopTimer()
}
}
// BenchmarkAccept runs the benchmark of accepting blocks
func BenchmarkAccept(b *testing.B) {
b.StopTimer()
b.ResetTimer()
genesisBytes, blocks := genGenesisStateBytes(
/*numBlocks=*/ 1,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
for n := 0; n < b.N; n++ {
vm := &VM{}
vm.Initialize(
/*ctx=*/ snow.DefaultContextTest(),
/*db=*/ memdb.New(),
/*genesis=*/ genesisBytes,
/*engineChan=*/ make(chan common.Message, 1),
/*fxs=*/ nil,
)
for _, blockBytes := range blocks {
blk, err := vm.ParseBlock(blockBytes)
if err != nil {
b.Fatal(err)
}
if err := blk.Verify(); err != nil {
b.Fatal(err)
}
b.StartTimer()
blk.Accept()
b.StopTimer()
}
}
}
// ParseAndVerifyAndAccept runs the benchmark of parsing, verifying, and accepting blocks
func ParseAndVerifyAndAccept(numBlocks, numTxsPerBlock int, b *testing.B) {
b.StopTimer()
b.ResetTimer()
genesisBytes, blocks := genGenesisStateBytes(
/*numBlocks=*/ numBlocks,
/*numTxsPerBlock=*/ numTxsPerBlock,
/*testing=*/ b,
)
for n := 0; n < b.N; n++ {
vm := &VM{}
vm.Initialize(
/*ctx=*/ snow.DefaultContextTest(),
/*db=*/ memdb.New(),
/*genesis=*/ genesisBytes,
/*engineChan=*/ make(chan common.Message, 1),
/*fxs=*/ nil,
)
b.StartTimer()
for _, blockBytes := range blocks {
blk, err := vm.ParseBlock(blockBytes)
if err != nil {
b.Fatal(err)
}
if err := blk.Verify(); err != nil {
b.Fatal(err)
}
blk.Accept()
}
b.StopTimer()
}
}
// BenchmarkParseAndVerifyAndAccept1 runs the benchmark of parsing, verifying, and accepting 1 block
func BenchmarkParseAndVerifyAndAccept1(b *testing.B) {
ParseAndVerifyAndAccept(
/*numBlocks=*/ 1,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
}
// BenchmarkParseAndVerifyAndAccept10 runs the benchmark of parsing, verifying, and accepting 10 blocks
func BenchmarkParseAndVerifyAndAccept10(b *testing.B) {
ParseAndVerifyAndAccept(
/*numBlocks=*/ 10,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
}
// ParseThenVerifyThenAccept runs the benchmark of parsing then verifying and then accepting blocks
func ParseThenVerifyThenAccept(numBlocks, numTxsPerBlock int, b *testing.B) {
b.StopTimer()
b.ResetTimer()
genesisBytes, blocks := genGenesisStateBytes(
/*numBlocks=*/ numBlocks,
/*numTxsPerBlock=*/ numTxsPerBlock,
/*testing=*/ b,
)
for n := 0; n < b.N; n++ {
vm := &VM{}
vm.Initialize(
/*ctx=*/ snow.DefaultContextTest(),
/*db=*/ memdb.New(),
/*genesis=*/ genesisBytes,
/*engineChan=*/ make(chan common.Message, 1),
/*fxs=*/ nil,
)
b.StartTimer()
parsedBlocks := make([]snowman.Block, len(blocks))
for i, blockBytes := range blocks {
blk, err := vm.ParseBlock(blockBytes)
if err != nil {
b.Fatal(err)
}
parsedBlocks[i] = blk
}
for _, blk := range parsedBlocks {
if err := blk.Verify(); err != nil {
b.Fatal(err)
}
}
for _, blk := range parsedBlocks {
blk.Accept()
}
b.StopTimer()
}
}
// BenchmarkParseThenVerifyThenAccept1 runs the benchmark of parsing then verifying and then accepting 1 block
func BenchmarkParseThenVerifyThenAccept1(b *testing.B) {
ParseThenVerifyThenAccept(
/*numBlocks=*/ 1,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
}
// BenchmarkParseThenVerifyThenAccept10 runs the benchmark of parsing then verifying and then accepting 10 blocks
func BenchmarkParseThenVerifyThenAccept10(b *testing.B) {
ParseThenVerifyThenAccept(
/*numBlocks=*/ 10,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
}
// IssueAndVerifyAndAccept runs the benchmark of issuing, verifying, and accepting blocks
func IssueAndVerifyAndAccept(numBlocks, numTxsPerBlock int, b *testing.B) {
b.StopTimer()
b.ResetTimer()
genesisBytes, blocks := genGenesisState(
/*numBlocks=*/ numBlocks,
/*numTxsPerBlock=*/ numTxsPerBlock,
/*testing=*/ b,
)
for n := 0; n < b.N; n++ {
vm := &VM{}
vm.Initialize(
/*ctx=*/ snow.DefaultContextTest(),
/*db=*/ memdb.New(),
/*genesis=*/ genesisBytes,
/*engineChan=*/ make(chan common.Message, 1),
/*fxs=*/ nil,
)
vm.SetPreference(vm.LastAccepted())
b.StartTimer()
for _, block := range blocks {
for _, tx := range block.txs {
if _, err := vm.IssueTx(tx.Bytes(), nil); err != nil {
b.Fatal(err)
}
}
blk, err := vm.BuildBlock()
if err != nil {
b.Fatal(err)
}
if err := blk.Verify(); err != nil {
b.Fatal(err)
}
vm.SetPreference(blk.ID())
blk.Accept()
}
b.StopTimer()
}
}
// BenchmarkIssueAndVerifyAndAccept1 runs the benchmark of issuing, verifying, and accepting 1 block
func BenchmarkIssueAndVerifyAndAccept1(b *testing.B) {
IssueAndVerifyAndAccept(
/*numBlocks=*/ 1,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
}
// BenchmarkIssueAndVerifyAndAccept10 runs the benchmark of issuing, verifying, and accepting 10 blocks
func BenchmarkIssueAndVerifyAndAccept10(b *testing.B) {
IssueAndVerifyAndAccept(
/*numBlocks=*/ 10,
/*numTxsPerBlock=*/ 1,
/*testing=*/ b,
)
}