aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Johnson <benbjohnson@yahoo.com>2014-04-30 12:27:54 -0600
committerBen Johnson <benbjohnson@yahoo.com>2014-04-30 12:27:54 -0600
commitd48c4a20be33a5d5d8a891c120de83d148334cc6 (patch)
tree192814044780f9c8b84892b88d10a04de7e4956a
parentMerge pull request #146 from benbjohnson/bench-batch (diff)
downloaddedo-d48c4a20be33a5d5d8a891c120de83d148334cc6.tar.gz
dedo-d48c4a20be33a5d5d8a891c120de83d148334cc6.tar.xz
Add streaming stats to bolt bench.
This commit adds -stats-interval to the 'bolt bench' utility. By setting this argument to an interval greater than 0s, the benchmark tool will output stats as streaming JSON. This data can, in turn, be graphed to understand performance over time.
-rw-r--r--cmd/bolt/bench.go56
-rw-r--r--cmd/bolt/main.go28
2 files changed, 61 insertions, 23 deletions
diff --git a/cmd/bolt/bench.go b/cmd/bolt/bench.go
index 10a5599..fef8e54 100644
--- a/cmd/bolt/bench.go
+++ b/cmd/bolt/bench.go
@@ -2,6 +2,7 @@ package main
import (
"encoding/binary"
+ "encoding/json"
"errors"
"fmt"
"io/ioutil"
@@ -42,6 +43,11 @@ func Bench(options *BenchOptions) {
}
defer db.Close()
+ // Enable streaming stats.
+ if options.StatsInterval > 0 {
+ go printStats(db, options.StatsInterval)
+ }
+
// Start profiling for writes.
if options.ProfileMode == "rw" || options.ProfileMode == "w" {
benchStartProfiling(options)
@@ -73,9 +79,9 @@ func Bench(options *BenchOptions) {
}
// Print results.
- fmt.Printf("# Write\t%v\t(%v/op)\t(%v op/sec)\n", results.WriteDuration, results.WriteOpDuration(), results.WriteOpsPerSecond())
- fmt.Printf("# Read\t%v\t(%v/op)\t(%v op/sec)\n", results.ReadDuration, results.ReadOpDuration(), results.ReadOpsPerSecond())
- fmt.Println("")
+ fmt.Fprintf(os.Stderr, "# Write\t%v\t(%v/op)\t(%v op/sec)\n", results.WriteDuration, results.WriteOpDuration(), results.WriteOpsPerSecond())
+ fmt.Fprintf(os.Stderr, "# Read\t%v\t(%v/op)\t(%v op/sec)\n", results.ReadDuration, results.ReadOpDuration(), results.ReadOpsPerSecond())
+ fmt.Fprintln(os.Stderr, "")
}
// Writes to the database.
@@ -233,18 +239,42 @@ func benchStopProfiling() {
}
}
+// Continuously prints stats on the database at given intervals.
+func printStats(db *bolt.DB, interval time.Duration) {
+ var prevStats = db.Stats()
+ var encoder = json.NewEncoder(os.Stdout)
+
+ for {
+ // Wait for the stats interval.
+ time.Sleep(interval)
+
+ // Retrieve new stats and find difference from previous iteration.
+ var stats = db.Stats()
+ var diff = stats.Sub(&prevStats)
+
+ // Print as JSON to STDOUT.
+ if err := encoder.Encode(diff); err != nil {
+ fatal(err)
+ }
+
+ // Save stats for next iteration.
+ prevStats = stats
+ }
+}
+
// BenchOptions represents the set of options that can be passed to Bench().
type BenchOptions struct {
- ProfileMode string
- WriteMode string
- ReadMode string
- Iterations int
- BatchSize int
- KeySize int
- ValueSize int
- CPUProfile string
- MemProfile string
- BlockProfile string
+ ProfileMode string
+ WriteMode string
+ ReadMode string
+ Iterations int
+ BatchSize int
+ KeySize int
+ ValueSize int
+ CPUProfile string
+ MemProfile string
+ BlockProfile string
+ StatsInterval time.Duration
}
// BenchResults represents the performance results of the benchmark.
diff --git a/cmd/bolt/main.go b/cmd/bolt/main.go
index cb2d47a..3558500 100644
--- a/cmd/bolt/main.go
+++ b/cmd/bolt/main.go
@@ -6,6 +6,7 @@ import (
"fmt"
"log"
"os"
+ "time"
"github.com/codegangsta/cli"
)
@@ -104,19 +105,26 @@ func NewApp() *cli.App {
&cli.StringFlag{Name: "cpuprofile", Usage: "CPU profile output path"},
&cli.StringFlag{Name: "memprofile", Usage: "Memory profile output path"},
&cli.StringFlag{Name: "blockprofile", Usage: "Block profile output path"},
+ &cli.StringFlag{Name: "stats-interval", Value: "0s", Usage: "Continuous stats interval"},
},
Action: func(c *cli.Context) {
+ statsInterval, err := time.ParseDuration(c.String("stats-interval"))
+ if err != nil {
+ fatal(err)
+ }
+
Bench(&BenchOptions{
- ProfileMode: c.String("profile-mode"),
- WriteMode: c.String("write-mode"),
- ReadMode: c.String("read-mode"),
- Iterations: c.Int("count"),
- BatchSize: c.Int("batch-size"),
- KeySize: c.Int("key-size"),
- ValueSize: c.Int("value-size"),
- CPUProfile: c.String("cpuprofile"),
- MemProfile: c.String("memprofile"),
- BlockProfile: c.String("blockprofile"),
+ ProfileMode: c.String("profile-mode"),
+ WriteMode: c.String("write-mode"),
+ ReadMode: c.String("read-mode"),
+ Iterations: c.Int("count"),
+ BatchSize: c.Int("batch-size"),
+ KeySize: c.Int("key-size"),
+ ValueSize: c.Int("value-size"),
+ CPUProfile: c.String("cpuprofile"),
+ MemProfile: c.String("memprofile"),
+ BlockProfile: c.String("blockprofile"),
+ StatsInterval: statsInterval,
})
},
}}