From c191e04ee7bb4043ab3ccb7ebeab16635be494bc Mon Sep 17 00:00:00 2001 From: Leo Balduf Date: Sun, 19 Jun 2016 12:50:21 -0400 Subject: [PATCH] store: add StringStore benchmarks --- server/store/memory/string_store_test.go | 85 ++++++- server/store/store_bench.go | 298 +++++++++++++++++++++++ 2 files changed, 381 insertions(+), 2 deletions(-) create mode 100644 server/store/store_bench.go diff --git a/server/store/memory/string_store_test.go b/server/store/memory/string_store_test.go index ccf5065..46719d2 100644 --- a/server/store/memory/string_store_test.go +++ b/server/store/memory/string_store_test.go @@ -11,10 +11,91 @@ import ( ) var ( - driver = &stringStoreDriver{} - stringStoreTester = store.PrepareStringStoreTester(driver) + driver = &stringStoreDriver{} + stringStoreTester = store.PrepareStringStoreTester(driver) + stringStoreBenchmarker = store.PrepareStringStoreBenchmarker(&stringStoreDriver{}) ) func TestStringStore(t *testing.T) { stringStoreTester.TestStringStore(t, &store.DriverConfig{}) } + +func BenchmarkStringStore_AddShort(b *testing.B) { + stringStoreBenchmarker.AddShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_AddLong(b *testing.B) { + stringStoreBenchmarker.AddLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_LookupShort(b *testing.B) { + stringStoreBenchmarker.LookupShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_LookupLong(b *testing.B) { + stringStoreBenchmarker.LookupLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_AddRemoveShort(b *testing.B) { + stringStoreBenchmarker.AddRemoveShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_AddRemoveLong(b *testing.B) { + stringStoreBenchmarker.AddRemoveLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_LookupNonExistShort(b *testing.B) { + stringStoreBenchmarker.LookupNonExistShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_LookupNonExistLong(b *testing.B) { + stringStoreBenchmarker.LookupNonExistLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_RemoveNonExistShort(b *testing.B) { + stringStoreBenchmarker.RemoveNonExistShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_RemoveNonExistLong(b *testing.B) { + stringStoreBenchmarker.RemoveNonExistLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_Add1KShort(b *testing.B) { + stringStoreBenchmarker.Add1KShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_Add1KLong(b *testing.B) { + stringStoreBenchmarker.Add1KLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_Lookup1KShort(b *testing.B) { + stringStoreBenchmarker.Lookup1KShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_Lookup1KLong(b *testing.B) { + stringStoreBenchmarker.Lookup1KLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_AddRemove1KShort(b *testing.B) { + stringStoreBenchmarker.AddRemove1KShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_AddRemove1KLong(b *testing.B) { + stringStoreBenchmarker.AddRemove1KLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_LookupNonExist1KShort(b *testing.B) { + stringStoreBenchmarker.LookupNonExist1KShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_LookupNonExist1KLong(b *testing.B) { + stringStoreBenchmarker.LookupNonExist1KLong(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_RemoveNonExist1KShort(b *testing.B) { + stringStoreBenchmarker.RemoveNonExist1KShort(b, &store.DriverConfig{}) +} + +func BenchmarkStringStore_RemoveNonExist1KLong(b *testing.B) { + stringStoreBenchmarker.RemoveNonExist1KLong(b, &store.DriverConfig{}) +} diff --git a/server/store/store_bench.go b/server/store/store_bench.go new file mode 100644 index 0000000..1d752bf --- /dev/null +++ b/server/store/store_bench.go @@ -0,0 +1,298 @@ +// Copyright 2016 The Chihaya Authors. All rights reserved. +// Use of this source code is governed by the BSD 2-Clause license, +// which can be found in the LICENSE file. + +package store + +import ( + "fmt" + "strings" + "testing" + + "github.com/stretchr/testify/require" +) + +const num1KElements = 1000 + +// StringStoreBenchmarker is a collection of benchmarks for StringStore drivers. +// Every benchmark expects a new, clean storage. Every benchmark should be +// called with a DriverConfig that ensures this. +type StringStoreBenchmarker interface { + AddShort(*testing.B, *DriverConfig) + AddLong(*testing.B, *DriverConfig) + LookupShort(*testing.B, *DriverConfig) + LookupLong(*testing.B, *DriverConfig) + AddRemoveShort(*testing.B, *DriverConfig) + AddRemoveLong(*testing.B, *DriverConfig) + LookupNonExistShort(*testing.B, *DriverConfig) + LookupNonExistLong(*testing.B, *DriverConfig) + RemoveNonExistShort(*testing.B, *DriverConfig) + RemoveNonExistLong(*testing.B, *DriverConfig) + + Add1KShort(*testing.B, *DriverConfig) + Add1KLong(*testing.B, *DriverConfig) + Lookup1KShort(*testing.B, *DriverConfig) + Lookup1KLong(*testing.B, *DriverConfig) + AddRemove1KShort(*testing.B, *DriverConfig) + AddRemove1KLong(*testing.B, *DriverConfig) + LookupNonExist1KShort(*testing.B, *DriverConfig) + LookupNonExist1KLong(*testing.B, *DriverConfig) + RemoveNonExist1KShort(*testing.B, *DriverConfig) + RemoveNonExist1KLong(*testing.B, *DriverConfig) +} + +var _ StringStoreBenchmarker = &stringStoreBench{} + +type stringStoreBench struct { + // sShort holds differentStrings unique strings of length 10. + sShort [num1KElements]string + // sLong holds differentStrings unique strings of length 1000. + sLong [num1KElements]string + + driver StringStoreDriver +} + +func generateLongStrings() (a [num1KElements]string) { + b := make([]byte, 2) + for i := range a { + b[0] = byte(i) + b[1] = byte(i >> 8) + a[i] = strings.Repeat(fmt.Sprintf("%x", b), 250) + } + + return +} + +func generateShortStrings() (a [num1KElements]string) { + b := make([]byte, 2) + for i := range a { + b[0] = byte(i) + b[1] = byte(i >> 8) + a[i] = strings.Repeat(fmt.Sprintf("%x", b), 3)[:10] + } + + return +} + +// PrepareStringStoreBenchmarker prepares a reusable suite for StringStore driver +// benchmarks. +func PrepareStringStoreBenchmarker(driver StringStoreDriver) StringStoreBenchmarker { + return stringStoreBench{ + sShort: generateShortStrings(), + sLong: generateLongStrings(), + driver: driver, + } +} + +type stringStoreSetupFunc func(StringStore) error + +func stringStoreSetupNOP(StringStore) error { return nil } + +type stringStoreBenchFunc func(StringStore, int) error + +func (sb stringStoreBench) runBenchmark(b *testing.B, cfg *DriverConfig, setup stringStoreSetupFunc, execute stringStoreBenchFunc) { + ss, err := sb.driver.New(cfg) + require.Nil(b, err, "Constructor error must be nil") + require.NotNil(b, ss, "String store must not be nil") + + err = setup(ss) + require.Nil(b, err, "Benchmark setup must not fail") + + b.ResetTimer() + for i := 0; i < b.N; i++ { + execute(ss, i) + } + b.StopTimer() + + errChan := ss.Stop() + err = <-errChan + require.Nil(b, err, "StringStore shutdown must not fail") +} + +func (sb stringStoreBench) AddShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sShort[0]) + return nil + }) +} + +func (sb stringStoreBench) AddLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sLong[0]) + return nil + }) +} + +func (sb stringStoreBench) Add1KShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sShort[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) Add1KLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sLong[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) LookupShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, + func(ss StringStore) error { + return ss.PutString(sb.sShort[0]) + }, + func(ss StringStore, i int) error { + ss.HasString(sb.sShort[0]) + return nil + }) +} + +func (sb stringStoreBench) LookupLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, + func(ss StringStore) error { + return ss.PutString(sb.sLong[0]) + }, + func(ss StringStore, i int) error { + ss.HasString(sb.sLong[0]) + return nil + }) +} + +func (sb stringStoreBench) Lookup1KShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, + func(ss StringStore) error { + for i := 0; i < num1KElements; i++ { + err := ss.PutString(sb.sShort[i]) + if err != nil { + return err + } + } + return nil + }, + func(ss StringStore, i int) error { + ss.HasString(sb.sShort[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) Lookup1KLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, + func(ss StringStore) error { + for i := 0; i < num1KElements; i++ { + err := ss.PutString(sb.sLong[i]) + if err != nil { + return err + } + } + return nil + }, + func(ss StringStore, i int) error { + ss.HasString(sb.sLong[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) AddRemoveShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sShort[0]) + ss.RemoveString(sb.sShort[0]) + return nil + }) +} + +func (sb stringStoreBench) AddRemoveLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sLong[0]) + ss.RemoveString(sb.sLong[0]) + return nil + }) +} + +func (sb stringStoreBench) AddRemove1KShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sShort[i%num1KElements]) + ss.RemoveString(sb.sShort[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) AddRemove1KLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.PutString(sb.sLong[i%num1KElements]) + ss.RemoveString(sb.sLong[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) LookupNonExistShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.HasString(sb.sShort[0]) + return nil + }) +} + +func (sb stringStoreBench) LookupNonExistLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.HasString(sb.sLong[0]) + return nil + }) +} + +func (sb stringStoreBench) LookupNonExist1KShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.HasString(sb.sShort[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) LookupNonExist1KLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.HasString(sb.sLong[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) RemoveNonExistShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.RemoveString(sb.sShort[0]) + return nil + }) +} + +func (sb stringStoreBench) RemoveNonExistLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.RemoveString(sb.sLong[0]) + return nil + }) +} + +func (sb stringStoreBench) RemoveNonExist1KShort(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.RemoveString(sb.sShort[i%num1KElements]) + return nil + }) +} + +func (sb stringStoreBench) RemoveNonExist1KLong(b *testing.B, cfg *DriverConfig) { + sb.runBenchmark(b, cfg, stringStoreSetupNOP, + func(ss StringStore, i int) error { + ss.RemoveString(sb.sLong[i%num1KElements]) + return nil + }) +}