From a42d74da7e6b3162701ae17d59647a6880ccb6bf Mon Sep 17 00:00:00 2001 From: Ben Johnson Date: Fri, 18 Apr 2014 21:37:45 -0500 Subject: Add 'bolt bench'. This commit adds a flexible benchmarking tool to the 'bolt' CLI. It allows the user to separately specify the write mode and read mode (e.g. sequential random, etc). It also allows the user to isolate profiling to either the read or the writes. Currently the bench tool only supports "seq" read and write modes. It also does not support streaming of Bolt counters yet. Fixes #95. /cc @snormore --- cmd/bolt/bench/bench.go | 126 --------------------------------------------- cmd/bolt/bench/config.go | 7 --- cmd/bolt/bench/generate.go | 24 --------- 3 files changed, 157 deletions(-) delete mode 100644 cmd/bolt/bench/bench.go delete mode 100644 cmd/bolt/bench/config.go delete mode 100644 cmd/bolt/bench/generate.go (limited to 'cmd/bolt/bench') diff --git a/cmd/bolt/bench/bench.go b/cmd/bolt/bench/bench.go deleted file mode 100644 index df584f2..0000000 --- a/cmd/bolt/bench/bench.go +++ /dev/null @@ -1,126 +0,0 @@ -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 -} diff --git a/cmd/bolt/bench/config.go b/cmd/bolt/bench/config.go deleted file mode 100644 index dea08fd..0000000 --- a/cmd/bolt/bench/config.go +++ /dev/null @@ -1,7 +0,0 @@ -package bench - -type Config struct { - ReadWriteMode string - TraversalPattern string - Parallelism int -} diff --git a/cmd/bolt/bench/generate.go b/cmd/bolt/bench/generate.go deleted file mode 100644 index 8c5554d..0000000 --- a/cmd/bolt/bench/generate.go +++ /dev/null @@ -1,24 +0,0 @@ -package bench - -import ( - "fmt" - "strings" - - "github.com/boltdb/bolt" -) - -// Generate and write data to specified number of buckets/items. -func GenerateDB(db *bolt.DB, numBuckets, numItemsPerBucket int) error { - return db.Update(func(tx *bolt.Tx) error { - for bucketIndex := 0; bucketIndex < numBuckets; bucketIndex++ { - bucketName := fmt.Sprintf("bucket%08d") - tx.CreateBucket([]byte(bucketName)) - bucket := tx.Bucket([]byte(bucketName)) - for i := 0; i < numItemsPerBucket; i++ { - value := []byte(strings.Repeat("0", 100)) - bucket.Put([]byte(fmt.Sprintf("key%08d", i)), value) - } - } - return nil - }) -} -- cgit v1.2.3