Skip to content

Commit

Permalink
feat(serverv2): add benchmarks of (old) cacheKV vs branch (#22497)
Browse files Browse the repository at this point in the history
  • Loading branch information
testinginprod authored Nov 22, 2024
1 parent 9d6d106 commit 3ebd7e5
Show file tree
Hide file tree
Showing 3 changed files with 173 additions and 10 deletions.
60 changes: 52 additions & 8 deletions server/v2/stf/branch/bench_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package branch

import (
"encoding/binary"
"fmt"
"testing"

Expand All @@ -20,28 +21,65 @@ func Benchmark_CacheStack_Set(b *testing.B) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_ = bs.Set([]byte{0}, []byte{0})
err := bs.Set([]byte{0}, []byte{0})
if err != nil {
b.Fatal(err)
}
}
})
}
}

var sink any

func Benchmark_Get(b *testing.B) {
for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
_, _ = bs.Get([]byte{0})
sink, _ = bs.Get([]byte{0})
}
})
}
if sink == nil {
b.Fatal("benchmark did not run")
}
sink = nil
}

func Benchmark_Iterate(b *testing.B) {
var keySink, valueSink any
func Benchmark_GetSparse(b *testing.B) {
var sink any
for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
keys := func() [][]byte {
var keys [][]byte
for i := 0; i < b.N; i++ {
keys = append(keys, numToBytes(i))
}
return keys
}()
b.ResetTimer()
b.ReportAllocs()
for _, key := range keys {
sink, _ = bs.Get(key)
}
})
}
if sink == nil {
b.Fatal("benchmark did not run")
}
sink = nil
}

var (
keySink any
valueSink any
)

func Benchmark_Iterate(b *testing.B) {
for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
Expand All @@ -58,9 +96,11 @@ func Benchmark_Iterate(b *testing.B) {
}
})
}

_ = keySink
_ = valueSink
if valueSink == nil || keySink == nil {
b.Fatal("benchmark did not run")
}
valueSink = nil
keySink = nil
}

// makeBranchStack creates a branch stack of the given size and initializes it with unique key-value pairs.
Expand All @@ -71,7 +111,7 @@ func makeBranchStack(b *testing.B, stackSize int) Store[store.KVStore] {
branch = NewStore[store.KVStore](branch)
for j := 0; j < elemsInStack; j++ {
// create unique keys by including the branch index.
key := []byte{byte(i), byte(j)}
key := append(numToBytes(i), numToBytes(j)...)
value := []byte{byte(j)}
err := branch.Set(key, value)
if err != nil {
Expand All @@ -81,3 +121,7 @@ func makeBranchStack(b *testing.B, stackSize int) Store[store.KVStore] {
}
return branch
}

func numToBytes[T ~int](n T) []byte {
return binary.BigEndian.AppendUint64(nil, uint64(n))
}
3 changes: 1 addition & 2 deletions server/v2/stf/branch/store.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,7 @@ func (s Store[T]) Get(key []byte) (value []byte, err error) {
if found {
return
}
// after we get it from parent store, we cache it.
// if it is not found in parent store, we still cache it as nil.
// if not found in the changeset, then check the parent.
value, err = s.parent.Get(key)
if err != nil {
return nil, err
Expand Down
120 changes: 120 additions & 0 deletions store/cachekv/branch_bench_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package cachekv_test

import (
"encoding/binary"
"fmt"
"testing"

coretesting "cosmossdk.io/core/testing"
"cosmossdk.io/store/cachekv"
"cosmossdk.io/store/dbadapter"
)

var (
stackSizes = []int{1, 10, 100}
elemsInStack = 10
)

func Benchmark_CacheStack_Set(b *testing.B) {
for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
bs.Set([]byte{0}, []byte{0})
}
})
}
}

// Gets the same key from the branch store.
func Benchmark_Get(b *testing.B) {
for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
sink = bs.Get([]byte{0})
}
})
}
if sink == nil {
b.Fatal("prevent compiler optimization")
}
sink = nil
}

// Gets always different keys.
func Benchmark_GetSparse(b *testing.B) {
for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
keys := func() [][]byte {
var keys [][]byte
for i := 0; i < b.N; i++ {
keys = append(keys, numToBytes(i))
}
return keys
}()
b.ResetTimer()
b.ReportAllocs()
for _, key := range keys {
sink = bs.Get(key)
}
})
}
if sink == nil {
b.Fatal("Benchmark did not run")
}
sink = nil
}

var keySink, valueSink any

func Benchmark_Iterate(b *testing.B) {

for _, stackSize := range stackSizes {
b.Run(fmt.Sprintf("StackSize%d", stackSize), func(b *testing.B) {
bs := makeBranchStack(b, stackSize)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
iter := bs.Iterator(nil, nil)
for iter.Valid() {
keySink = iter.Key()
valueSink = iter.Value()
iter.Next()
}
_ = iter.Close()
}
})
}

if keySink == nil || valueSink == nil {
b.Fatal("Benchmark did not run")
}
keySink = nil
valueSink = nil
}

// makeBranchStack creates a branch stack of the given size and initializes it with unique key-value pairs.
func makeBranchStack(_ *testing.B, stackSize int) *cachekv.Store {
parent := dbadapter.Store{DB: coretesting.NewMemDB()}
branch := cachekv.NewStore(parent)
for i := 1; i < stackSize; i++ {
branch = cachekv.NewStore(branch)
for j := 0; j < elemsInStack; j++ {
// create unique keys by including the branch index.
key := append(numToBytes(i), numToBytes(j)...)
value := []byte{byte(j)}
branch.Set(key, value)
}
}
return branch
}

func numToBytes[T ~int](n T) []byte {
return binary.BigEndian.AppendUint64(nil, uint64(n))
}

0 comments on commit 3ebd7e5

Please sign in to comment.