mirror of https://github.com/etcd-io/bbolt.git
Add benchmarks.
parent
3a1b152562
commit
64fcacedfa
|
@ -0,0 +1,2 @@
|
||||||
|
*.prof
|
||||||
|
*.test
|
6
Makefile
6
Makefile
|
@ -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
|
||||||
|
|
25
db_test.go
25
db_test.go
|
@ -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-")
|
||||||
|
|
|
@ -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
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue