Add benchmarks.

pull/34/head
Ben Johnson 2014-03-04 13:02:17 -07:00
parent 3a1b152562
commit 64fcacedfa
5 changed files with 106 additions and 1 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.prof
*.test

View File

@ -14,6 +14,10 @@ cover: fmt
go tool cover -html=$(COVERPROFILE) go tool cover -html=$(COVERPROFILE)
rm $(COVERPROFILE) rm $(COVERPROFILE)
cpuprofile: fmt
@go test -c
@./bolt.test -test.v -test.run="^X" -test.bench=$(BENCH) -test.cpuprofile cpu.prof
fmt: fmt:
@go fmt ./... @go fmt ./...
@ -25,4 +29,4 @@ test: fmt
@echo "=== RACE DETECTOR ===" @echo "=== RACE DETECTOR ==="
@go test -v -race -test.run=Parallel @go test -v -race -test.run=Parallel
.PHONY: bench cloc cover fmt test .PHONY: bench cloc cover cpuprofile fmt memprofile test

View File

@ -3,8 +3,10 @@ package bolt
import ( import (
"io" "io"
"io/ioutil" "io/ioutil"
"math/rand"
"os" "os"
"strconv" "strconv"
"strings"
"syscall" "syscall"
"testing" "testing"
"time" "time"
@ -341,6 +343,29 @@ func TestDBString(t *testing.T) {
assert.Equal(t, db.GoString(), `bolt.DB{path:"/tmp/foo"}`) assert.Equal(t, db.GoString(), `bolt.DB{path:"/tmp/foo"}`)
} }
// Benchmark the performance of single put transactions in random order.
func BenchmarkDBPutSequential(b *testing.B) {
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
db.CreateBucket("widgets")
for i := 0; i < b.N; i++ {
db.Put("widgets", []byte(strconv.Itoa(i)), value)
}
})
}
// Benchmark the performance of single put transactions in random order.
func BenchmarkDBPutRandom(b *testing.B) {
indexes := rand.Perm(b.N)
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
db.CreateBucket("widgets")
for i := 0; i < b.N; i++ {
db.Put("widgets", []byte(strconv.Itoa(indexes[i])), value)
}
})
}
// withDB executes a function with a database reference. // withDB executes a function with a database reference.
func withDB(fn func(*DB, string)) { func withDB(fn func(*DB, string)) {
f, _ := ioutil.TempFile("", "bolt-") f, _ := ioutil.TempFile("", "bolt-")

View File

@ -1,6 +1,8 @@
package bolt package bolt
import ( import (
"math/rand"
"strconv"
"strings" "strings"
"testing" "testing"
@ -140,3 +142,40 @@ func TestRWTransactionDeleteBucketNotFound(t *testing.T) {
assert.Equal(t, err, ErrBucketNotFound) assert.Equal(t, err, ErrBucketNotFound)
}) })
} }
// Benchmark the performance of bulk put transactions in random order.
func BenchmarkRWTransactionPutRandom(b *testing.B) {
indexes := rand.Perm(b.N)
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
db.CreateBucket("widgets")
var txn *RWTransaction
var bucket *Bucket
for i := 0; i < b.N; i++ {
if i%1000 == 0 {
if txn != nil {
txn.Commit()
}
txn, _ = db.RWTransaction()
bucket = txn.Bucket("widgets")
}
bucket.Put([]byte(strconv.Itoa(indexes[i])), value)
}
txn.Commit()
})
}
// Benchmark the performance of bulk put transactions in sequential order.
func BenchmarkRWTransactionPutSequential(b *testing.B) {
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
db.CreateBucket("widgets")
db.Do(func(txn *RWTransaction) error {
bucket := txn.Bucket("widgets")
for i := 0; i < b.N; i++ {
bucket.Put([]byte(strconv.Itoa(i)), value)
}
return nil
})
})
}

View File

@ -2,8 +2,11 @@ package bolt
import ( import (
"fmt" "fmt"
"math/rand"
"os" "os"
"sort" "sort"
"strconv"
"strings"
"testing" "testing"
"testing/quick" "testing/quick"
@ -228,3 +231,35 @@ func TestTransactionCursorIterateReverse(t *testing.T) {
} }
fmt.Fprint(os.Stderr, "\n") fmt.Fprint(os.Stderr, "\n")
} }
// Benchmark the performance iterating over a cursor.
func BenchmarkTransactionCursor(b *testing.B) {
indexes := rand.Perm(b.N)
value := []byte(strings.Repeat("0", 64))
withOpenDB(func(db *DB, path string) {
// Write data to bucket.
db.CreateBucket("widgets")
db.Do(func(txn *RWTransaction) error {
bucket := txn.Bucket("widgets")
for i := 0; i < b.N; i++ {
bucket.Put([]byte(strconv.Itoa(indexes[i])), value)
}
return nil
})
b.ResetTimer()
// Iterate over bucket using cursor.
db.With(func(txn *Transaction) error {
count := 0
c := txn.Bucket("widgets").Cursor()
for k, _ := c.First(); k != nil; k, _ = c.Next() {
count++
}
if count != b.N {
b.Fatalf("wrong count: %d; expected: %d", count, b.N)
}
return nil
})
})
}