blob: 1ba7d63a148938c0f06397525285c5a6b884d405 [file] [log] [blame]
// Copyright 2015 The Vanadium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This benchmark measures time spent on unsynced Put/Get/Delete/Scan/Query
// operations.
//
// All tests use 9-digit keys and values of type sampleStruct.
// 100K benchmarks use values with 100K byte values inside the struct.
//
// Results (jiri go test v.io/v23/syncbase/nosql -bench . -run Benchmark):
// BenchmarkPut-12 500 3681219 ns/op
// BenchmarkGet-12 500 2595279 ns/op
// BenchmarkDelete-12 500 3380728 ns/op
// BenchmarkScan-12 3000 402552 ns/op
// BenchmarkExec-12 20000 71024 ns/op
// BenchmarkPut100K-12 500 4435239 ns/op
// BenchmarkGet100K-12 500 3828251 ns/op
// BenchmarkDelete100K-12 500 3379342 ns/op
// BenchmarkScan100K-12 1000 1741592 ns/op
// BenchmarkExec100K-12 2000 1079510 ns/op
package nosql_test
import (
"fmt"
"math/rand"
"testing"
"v.io/v23/context"
wire "v.io/v23/services/syncbase/nosql"
"v.io/v23/syncbase"
"v.io/v23/syncbase/nosql"
_ "v.io/x/ref/runtime/factories/generic"
tu "v.io/x/ref/services/syncbase/testutil"
)
// prepare creates a service, app, database and table "tb" within the database,
// returning the context, handle to the database and table, and the clean up
// function.
func prepare() (*context.T, nosql.Database, nosql.Table, func()) {
ctx, sName, cleanup := tu.SetupOrDie(nil)
s := syncbase.NewService(sName)
a := s.App("a")
if err := a.Create(ctx, nil); err != nil {
panic(fmt.Sprintf("can't create an app: %v", err))
}
d := a.NoSQLDatabase("d", nil)
if err := d.Create(ctx, nil); err != nil {
panic(fmt.Sprintf("can't create a database: %v", err))
}
tb := d.Table("tb")
if err := tb.Create(ctx, nil); err != nil {
panic(fmt.Sprintf("can't create a table: %v", err))
}
return ctx, d, tb, cleanup
}
type testStruct struct {
Val string
Blob wire.BlobRef
}
type sampleStruct struct {
A string
B int
C *testStruct
D []byte
}
func generateSampleStruct() interface{} {
return sampleStruct{A: "hello, world!", B: 42}
}
func generate100KStruct() interface{} {
var byteSlice []byte
r := rand.New(rand.NewSource(23917))
for i := 0; i < 100*1000; i++ {
byteSlice = append(byteSlice, byte(r.Intn(256)))
}
return sampleStruct{A: "hello, world!", B: 42, D: byteSlice}
}
func generateTestData(b *testing.B, ctx *context.T, tb nosql.Table, value interface{}) {
for i := 0; i < b.N; i++ {
if err := tb.Put(ctx, fmt.Sprintf("%09d", i), value); err != nil {
b.Fatalf("can't generate test data: %v", err)
}
}
}
func runPutBenchmark(b *testing.B, value interface{}) {
ctx, _, tb, cleanup := prepare()
defer cleanup()
b.ResetTimer()
generateTestData(b, ctx, tb, value)
b.StopTimer()
}
func runGetBenchmark(b *testing.B, value interface{}) {
ctx, _, tb, cleanup := prepare()
defer cleanup()
generateTestData(b, ctx, tb, value)
b.ResetTimer()
for i := 0; i < b.N; i++ {
var got sampleStruct
if err := tb.Get(ctx, fmt.Sprintf("%09d", i), &got); err != nil {
b.Fatalf("tb.Get failed: %v", err)
}
}
b.StopTimer()
}
func runDeleteBenchmark(b *testing.B, value interface{}) {
ctx, _, tb, cleanup := prepare()
defer cleanup()
generateTestData(b, ctx, tb, value)
b.ResetTimer()
for i := 0; i < b.N; i++ {
if err := tb.Delete(ctx, fmt.Sprintf("%09d", i)); err != nil {
b.Fatalf("tb.Delete failed: %v", err)
}
}
b.StopTimer()
}
func runScanBenchmark(b *testing.B, value interface{}) {
ctx, _, tb, cleanup := prepare()
defer cleanup()
generateTestData(b, ctx, tb, value)
b.ResetTimer()
s := tb.Scan(ctx, nosql.Prefix(""))
for i := 0; i < b.N; i++ {
var got sampleStruct
s.Advance()
s.Value(&got)
}
b.StopTimer()
}
func runExecBenchmark(b *testing.B, value interface{}) {
ctx, d, tb, cleanup := prepare()
defer cleanup()
generateTestData(b, ctx, tb, value)
b.ResetTimer()
_, s, _ := d.Exec(ctx, "select v from tb")
for i := 0; i < b.N; i++ {
s.Advance()
s.Result()
}
b.StopTimer()
}
func BenchmarkPut(b *testing.B) {
runPutBenchmark(b, generateSampleStruct())
}
func BenchmarkGet(b *testing.B) {
runGetBenchmark(b, generateSampleStruct())
}
func BenchmarkDelete(b *testing.B) {
runDeleteBenchmark(b, generateSampleStruct())
}
func BenchmarkScan(b *testing.B) {
runScanBenchmark(b, generateSampleStruct())
}
func BenchmarkExec(b *testing.B) {
runExecBenchmark(b, generateSampleStruct())
}
func BenchmarkPut100K(b *testing.B) {
runPutBenchmark(b, generate100KStruct())
}
func BenchmarkGet100K(b *testing.B) {
runGetBenchmark(b, generate100KStruct())
}
func BenchmarkDelete100K(b *testing.B) {
runDeleteBenchmark(b, generate100KStruct())
}
func BenchmarkScan100K(b *testing.B) {
runScanBenchmark(b, generate100KStruct())
}
func BenchmarkExec100K(b *testing.B) {
runExecBenchmark(b, generate100KStruct())
}