feat(serverv2): add benchmarks of (old) cacheKV vs branch (#22497)

This commit is contained in:
testinginprod 2024-11-22 13:15:02 +01:00 committed by GitHub
parent 9d6d1067bc
commit 3ebd7e53ed
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 173 additions and 10 deletions

View File

@ -1,6 +1,7 @@
package branch
import (
"encoding/binary"
"fmt"
"testing"
@ -20,12 +21,17 @@ 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) {
@ -33,15 +39,47 @@ func Benchmark_Get(b *testing.B) {
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)
@ -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.
@ -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 {
@ -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))
}

View File

@ -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

View File

@ -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))
}