Commit 9c2ebb9b authored by Jan Mercl's avatar Jan Mercl

More benchmarks, more documentation

parent be48a068
......@@ -683,3 +683,84 @@ func TestEnumeratorPrev(t *testing.T) {
}
}
func BenchmarkSeekSeq(b *testing.B) {
t := TreeNew(cmp)
for i := 0; i < b.N; i++ {
t.Set(i, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
t.Seek(i)
}
}
func BenchmarkSeekRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
for _, v := range a {
r.Set(v, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Seek(v)
}
}
func BenchmarkNext1e3(b *testing.B) {
const N = 1e3
t := TreeNew(cmp)
for i := 0; i < N; i++ {
t.Set(i, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
en, err := t.SeekFirst()
if err != nil {
b.Fatal(err)
}
n := 0
for {
if _, _, err = en.Next(); err != nil {
break
}
n++
}
if n != N {
b.Fatal(n)
}
}
}
func BenchmarkPrev1e3(b *testing.B) {
const N = 1e3
t := TreeNew(cmp)
for i := 0; i < N; i++ {
t.Set(i, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
en, err := t.SeekLast()
if err != nil {
b.Fatal(err)
}
n := 0
for {
if _, _, err = en.Prev(); err != nil {
break
}
n++
}
if n != N {
b.Fatal(n)
}
}
}
......@@ -17,6 +17,47 @@
// CAPS) and every value type occurrence is replaced by the word 'value'
// (written in all CAPS). Then you have to replace theses strings with your
// desired type(s), using any technique you're comfortable with.
//
// This is how, for example, 'example/int.go' was created:
//
// $ mkdir example
// $
// $ # Note: the command bellow must be actually written using the words
// $ # 'key' and 'value' in all CAPS. The proper form is avoided in this
// $ # documentation to not confuse any text replacement mechanism.
// $
// $ make generic | sed -e 's/key/int/g' -e 's/value/int/g' > example/int.go
//
// No other changes to int.go are (strictly) necessary, it compiles just fine.
// In a next step, benchmarks from all_test.go were copied into
// example/bench_test.go without any changes. A comparator is defined in
// bench_test.go like this:
//
// func cmp(a, b int) int {
// return a - b
// }
//
// Running the benchmarks on a machine with Intel X5450 CPU @ 3 GHz:
//
// $ go test -bench . example/bench_test.go example/int.go
// testing: warning: no tests to run
// PASS
// BenchmarkSetSeq 5000000 590 ns/op
// BenchmarkSetRnd 1000000 1530 ns/op
// BenchmarkGetSeq 10000000 373 ns/op
// BenchmarkGetRnd 2000000 1109 ns/op
// BenchmarkDelSeq 5000000 672 ns/op
// BenchmarkDelRnd 1000000 1275 ns/op
// BenchmarkSeekSeq 5000000 552 ns/op
// BenchmarkSeekRnd 1000000 1108 ns/op
// BenchmarkNext1e3 200000 13414 ns/op
// BenchmarkPrev1e3 200000 13215 ns/op
// ok command-line-arguments 51.372s
// $
//
// Note that the Next and Prev benchmarks enumerate 1000 items (KV pairs), so
// getting the next or previous iterated item is performed in about 13 ns. This
// is the nice O(1) property of B+trees, usually not found in other tree types.
package b
import (
......@@ -33,9 +74,10 @@ const (
type (
// Cmp compares a and b. Return value is:
//
// -1 if a < b
// 0 if a == b
// +1 if a > b
// < 0 if a < b
// 0 if a == b
// > 0 if a > b
//
Cmp func(a, b interface{} /*K*/) int
d struct { // data page
......
// Copyright 2013 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package b
import (
"math"
"runtime/debug"
"testing"
"github.com/cznic/mathutil"
)
func cmp(a, b int) int {
return a - b
}
func rng() *mathutil.FC32 {
x, err := mathutil.NewFC32(math.MinInt32, math.MaxInt32, false)
if err != nil {
panic(err)
}
return x
}
func BenchmarkSetSeq(b *testing.B) {
r := TreeNew(cmp)
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Set(i, i)
}
}
func BenchmarkSetRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Set(v, 0)
}
}
func BenchmarkGetSeq(b *testing.B) {
r := TreeNew(cmp)
for i := 0; i < b.N; i++ {
r.Set(i, i)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Get(i)
}
}
func BenchmarkGetRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
for _, v := range a {
r.Set(v, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Get(v)
}
}
func BenchmarkDelSeq(b *testing.B) {
r := TreeNew(cmp)
for i := 0; i < b.N; i++ {
r.Set(i, i)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
r.Delete(i)
}
}
func BenchmarkDelRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
for _, v := range a {
r.Set(v, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Delete(v)
}
}
func BenchmarkSeekSeq(b *testing.B) {
t := TreeNew(cmp)
for i := 0; i < b.N; i++ {
t.Set(i, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
t.Seek(i)
}
}
func BenchmarkSeekRnd(b *testing.B) {
r := TreeNew(cmp)
rng := rng()
a := make([]int, b.N)
for i := range a {
a[i] = rng.Next()
}
for _, v := range a {
r.Set(v, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for _, v := range a {
r.Seek(v)
}
}
func BenchmarkNext1e3(b *testing.B) {
const N = 1e3
t := TreeNew(cmp)
for i := 0; i < N; i++ {
t.Set(i, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
en, err := t.SeekFirst()
if err != nil {
b.Fatal(err)
}
n := 0
for {
if _, _, err = en.Next(); err != nil {
break
}
n++
}
if n != N {
b.Fatal(n)
}
}
}
func BenchmarkPrev1e3(b *testing.B) {
const N = 1e3
t := TreeNew(cmp)
for i := 0; i < N; i++ {
t.Set(i, 0)
}
debug.FreeOSMemory()
b.ResetTimer()
for i := 0; i < b.N; i++ {
en, err := t.SeekLast()
if err != nil {
b.Fatal(err)
}
n := 0
for {
if _, _, err = en.Prev(); err != nil {
break
}
n++
}
if n != N {
b.Fatal(n)
}
}
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment