aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile6
-rw-r--r--db_test.go25
-rw-r--r--rwtransaction_test.go39
-rw-r--r--transaction_test.go35
5 files changed, 106 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..215e0cc
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+*.prof
+*.test
diff --git a/Makefile b/Makefile
index 29ea2f5..4cc71b6 100644
--- a/Makefile
+++ b/Makefile
@@ -14,6 +14,10 @@ cover: fmt
go tool cover -html=$(COVERPROFILE)
rm $(COVERPROFILE)
+cpuprofile: fmt
+ @go test -c
+ @./bolt.test -test.v -test.run="^X" -test.bench=$(BENCH) -test.cpuprofile cpu.prof
+
fmt:
@go fmt ./...
@@ -25,4 +29,4 @@ test: fmt
@echo "=== RACE DETECTOR ==="
@go test -v -race -test.run=Parallel
-.PHONY: bench cloc cover fmt test
+.PHONY: bench cloc cover cpuprofile fmt memprofile test
diff --git a/db_test.go b/db_test.go
index 2b7975c..c8a8267 100644
--- a/db_test.go
+++ b/db_test.go
@@ -3,8 +3,10 @@ package bolt
import (
"io"
"io/ioutil"
+ "math/rand"
"os"
"strconv"
+ "strings"
"syscall"
"testing"
"time"
@@ -341,6 +343,29 @@ func TestDBString(t *testing.T) {
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.
func withDB(fn func(*DB, string)) {
f, _ := ioutil.TempFile("", "bolt-")
diff --git a/rwtransaction_test.go b/rwtransaction_test.go
index 1635b45..e45ec10 100644
--- a/rwtransaction_test.go
+++ b/rwtransaction_test.go
@@ -1,6 +1,8 @@
package bolt
import (
+ "math/rand"
+ "strconv"
"strings"
"testing"
@@ -140,3 +142,40 @@ func TestRWTransactionDeleteBucketNotFound(t *testing.T) {
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
+ })
+ })
+}
diff --git a/transaction_test.go b/transaction_test.go
index 8cf9dfa..04cb44b 100644
--- a/transaction_test.go
+++ b/transaction_test.go
@@ -2,8 +2,11 @@ package bolt
import (
"fmt"
+ "math/rand"
"os"
"sort"
+ "strconv"
+ "strings"
"testing"
"testing/quick"
@@ -228,3 +231,35 @@ func TestTransactionCursorIterateReverse(t *testing.T) {
}
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
+ })
+ })
+}