Merge pull request #147 from benbjohnson/stats

Add streaming stats to bolt bench.
pull/34/head
Ben Johnson 2014-05-01 15:13:05 -06:00
commit a18135e055
2 changed files with 61 additions and 23 deletions

View File

@ -2,6 +2,7 @@ package main
import ( import (
"encoding/binary" "encoding/binary"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io/ioutil"
@ -42,6 +43,11 @@ func Bench(options *BenchOptions) {
} }
defer db.Close() defer db.Close()
// Enable streaming stats.
if options.StatsInterval > 0 {
go printStats(db, options.StatsInterval)
}
// Start profiling for writes. // Start profiling for writes.
if options.ProfileMode == "rw" || options.ProfileMode == "w" { if options.ProfileMode == "rw" || options.ProfileMode == "w" {
benchStartProfiling(options) benchStartProfiling(options)
@ -73,9 +79,9 @@ func Bench(options *BenchOptions) {
} }
// Print results. // Print results.
fmt.Printf("# Write\t%v\t(%v/op)\t(%v op/sec)\n", results.WriteDuration, results.WriteOpDuration(), results.WriteOpsPerSecond()) fmt.Fprintf(os.Stderr, "# 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.Fprintf(os.Stderr, "# Read\t%v\t(%v/op)\t(%v op/sec)\n", results.ReadDuration, results.ReadOpDuration(), results.ReadOpsPerSecond())
fmt.Println("") fmt.Fprintln(os.Stderr, "")
} }
// Writes to the database. // 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(). // BenchOptions represents the set of options that can be passed to Bench().
type BenchOptions struct { type BenchOptions struct {
ProfileMode string ProfileMode string
WriteMode string WriteMode string
ReadMode string ReadMode string
Iterations int Iterations int
BatchSize int BatchSize int
KeySize int KeySize int
ValueSize int ValueSize int
CPUProfile string CPUProfile string
MemProfile string MemProfile string
BlockProfile string BlockProfile string
StatsInterval time.Duration
} }
// BenchResults represents the performance results of the benchmark. // BenchResults represents the performance results of the benchmark.

View File

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"log" "log"
"os" "os"
"time"
"github.com/codegangsta/cli" "github.com/codegangsta/cli"
) )
@ -104,19 +105,26 @@ func NewApp() *cli.App {
&cli.StringFlag{Name: "cpuprofile", Usage: "CPU profile output path"}, &cli.StringFlag{Name: "cpuprofile", Usage: "CPU profile output path"},
&cli.StringFlag{Name: "memprofile", Usage: "Memory profile output path"}, &cli.StringFlag{Name: "memprofile", Usage: "Memory profile output path"},
&cli.StringFlag{Name: "blockprofile", Usage: "Block 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) { Action: func(c *cli.Context) {
statsInterval, err := time.ParseDuration(c.String("stats-interval"))
if err != nil {
fatal(err)
}
Bench(&BenchOptions{ Bench(&BenchOptions{
ProfileMode: c.String("profile-mode"), ProfileMode: c.String("profile-mode"),
WriteMode: c.String("write-mode"), WriteMode: c.String("write-mode"),
ReadMode: c.String("read-mode"), ReadMode: c.String("read-mode"),
Iterations: c.Int("count"), Iterations: c.Int("count"),
BatchSize: c.Int("batch-size"), BatchSize: c.Int("batch-size"),
KeySize: c.Int("key-size"), KeySize: c.Int("key-size"),
ValueSize: c.Int("value-size"), ValueSize: c.Int("value-size"),
CPUProfile: c.String("cpuprofile"), CPUProfile: c.String("cpuprofile"),
MemProfile: c.String("memprofile"), MemProfile: c.String("memprofile"),
BlockProfile: c.String("blockprofile"), BlockProfile: c.String("blockprofile"),
StatsInterval: statsInterval,
}) })
}, },
}} }}