diff options
author | Steven Normore <snormore@gmail.com> | 2014-04-14 16:25:04 +0000 |
---|---|---|
committer | Ben Johnson <benbjohnson@yahoo.com> | 2014-04-18 21:44:48 -0500 |
commit | 71e91e24b064c1c8e33d92b7f324b6cd57d07f87 (patch) | |
tree | 58863c8077373f832b2cf608f8c746faf9cc9438 /cmd/bolt/bench/bench.go | |
parent | add bench sub-package (diff) | |
download | dedo-71e91e24b064c1c8e33d92b7f324b6cd57d07f87.tar.gz dedo-71e91e24b064c1c8e33d92b7f324b6cd57d07f87.tar.xz |
move bench package to bench/cmd/bolt/bench
Diffstat (limited to 'cmd/bolt/bench/bench.go')
-rw-r--r-- | cmd/bolt/bench/bench.go | 126 |
1 files changed, 126 insertions, 0 deletions
diff --git a/cmd/bolt/bench/bench.go b/cmd/bolt/bench/bench.go new file mode 100644 index 0000000..df584f2 --- /dev/null +++ b/cmd/bolt/bench/bench.go @@ -0,0 +1,126 @@ +package bench + +import ( + "errors" + "fmt" + "sync" + "testing" + + "github.com/boltdb/bolt" +) + +const ( + BenchReadMode = "read" + BenchWriteMode = "write" + BenchSequentialTraversal = "sequential" + BenchRandomTraversal = "random" +) + +type Benchmark struct { + db *bolt.DB + config *Config +} + +func New(db *bolt.DB, config *Config) *Benchmark { + b := new(Benchmark) + b.db = db + b.config = config + return b +} + +func (bm *Benchmark) Run(b *testing.B) { + + // Read buckets and keys before benchmark begins so we don't knew the + // results. + buckets, err := buckets(bm.db) + if err != nil { + b.Fatalf("error: %+v", err) + } + bucketsWithKeys := make(map[string][]string) + for _, bucket := range buckets { + keys, err := keys(bm.db, bucket) + if err != nil { + b.Fatalf("error: %+v", err) + } + bucketsWithKeys[bucket] = keys + } + + b.ResetTimer() + + // Keep running a fixed number of parallel reads until we run out of time. + for i := 0; i < b.N; i++ { + var wg sync.WaitGroup + for j := 0; j < bm.config.Parallelism; j++ { + wg.Add(1) + go func() { + defer wg.Done() + if err := bm.readBuckets(b, bm.db, bucketsWithKeys); err != nil { + b.Fatalf("error: %+v", err) + } + }() + } + wg.Wait() + } +} + +// Run benchmark(s) for each of the given buckets. +func (bm *Benchmark) readBuckets(b *testing.B, db *bolt.DB, bucketsWithKeys map[string][]string) error { + return db.View(func(tx *bolt.Tx) error { + bucketsCount := len(bucketsWithKeys) + count := 0 + for bucket, keys := range bucketsWithKeys { + bucket := tx.Bucket([]byte(bucket)) + if err := bm.readKeys(b, bucket, keys); err != nil { + return err + } + count++ + } + if count != bucketsCount { + return errors.New(fmt.Sprintf("wrong count: %d; expected: %d", count, bucketsCount)) + } + return nil + }) +} + +func (bm *Benchmark) readKeys(b *testing.B, bucket *bolt.Bucket, keys []string) error { + c := bucket.Cursor() + keysCount := len(keys) + count := 0 + for k, _ := c.First(); k != nil; k, _ = c.Next() { + count++ + } + if count != keysCount { + return errors.New(fmt.Sprintf("wrong count: %d; expected: %d", count, keysCount)) + } + return nil +} + +func buckets(db *bolt.DB) ([]string, error) { + buckets := []string{} + err := db.View(func(tx *bolt.Tx) error { + // Iterate over each bucket. + return tx.ForEach(func(name []byte, _ *bolt.Bucket) error { + buckets = append(buckets, string(name)) + return nil + }) + }) + return buckets, err +} + +func keys(db *bolt.DB, bucket string) ([]string, error) { + keys := []string{} + err := db.View(func(tx *bolt.Tx) error { + // Find bucket. + b := tx.Bucket([]byte(bucket)) + if b == nil { + return errors.New(fmt.Sprintf("bucket %+v not found", b)) + } + + // Iterate over each key. + return b.ForEach(func(key, _ []byte) error { + keys = append(keys, string(key)) + return nil + }) + }) + return keys, err +} |