Commit 14175e51 authored by Jan Mercl's avatar Jan Mercl

Fix missed splits

parent 858434e3
......@@ -218,8 +218,8 @@ func TestSetGet0(t *testing.T) {
}
func TestSetGet1(t *testing.T) {
const N = 50000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x314259} {
const N = 60000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314259} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
......@@ -253,10 +253,6 @@ func TestSetGet1(t *testing.T) {
}
}
func BenchmarkSetSeq1e2(b *testing.B) {
benchmarkSetSeq(b, 1e2)
}
func BenchmarkSetSeq1e3(b *testing.B) {
benchmarkSetSeq(b, 1e3)
}
......@@ -287,10 +283,6 @@ func benchmarkSetSeq(b *testing.B, n int) {
b.StopTimer()
}
func BenchmarkGetSeq1e2(b *testing.B) {
benchmarkGetSeq(b, 1e2)
}
func BenchmarkGetSeq1e3(b *testing.B) {
benchmarkGetSeq(b, 1e3)
}
......@@ -322,10 +314,6 @@ func benchmarkGetSeq(b *testing.B, n int) {
b.StopTimer()
}
func BenchmarkSetRnd1e2(b *testing.B) {
benchmarkSetRnd(b, 1e2)
}
func BenchmarkSetRnd1e3(b *testing.B) {
benchmarkSetRnd(b, 1e3)
}
......@@ -361,10 +349,6 @@ func benchmarkSetRnd(b *testing.B, n int) {
b.StopTimer()
}
func BenchmarkGetRnd1e2(b *testing.B) {
benchmarkGetRnd(b, 1e2)
}
func BenchmarkGetRnd1e3(b *testing.B) {
benchmarkGetRnd(b, 1e3)
}
......@@ -402,8 +386,8 @@ func benchmarkGetRnd(b *testing.B, n int) {
}
func TestSetGet2(t *testing.T) {
const N = 50000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x314259} {
const N = 60000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314259} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
......@@ -548,8 +532,8 @@ func TestDelete0(t *testing.T) {
}
func TestDelete1(t *testing.T) {
const N = 60000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x314259} {
const N = 70000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314259} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
......@@ -573,10 +557,6 @@ func TestDelete1(t *testing.T) {
}
}
func benchmarkDelSeq1e2(b *testing.B) {
benchmarkDelSeq(b, 1e2)
}
func benchmarkDelSeq1e3(b *testing.B) {
benchmarkDelSeq(b, 1e3)
}
......@@ -610,10 +590,6 @@ func benchmarkDelSeq(b *testing.B, n int) {
b.StopTimer()
}
func BenchmarkDelRnd1e2(b *testing.B) {
benchmarkDelRnd(b, 1e2)
}
func BenchmarkDelRnd1e3(b *testing.B) {
benchmarkDelRnd(b, 1e3)
}
......@@ -653,8 +629,8 @@ func benchmarkDelRnd(b *testing.B, n int) {
}
func TestDelete2(t *testing.T) {
const N = 50000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x314259} {
const N = 60000
for _, x := range []int{0, -1, 0x555555, 0xaaaaaa, 0x333333, 0xcccccc, 0x314259} {
r := TreeNew(cmp)
set := r.Set
a := make([]int, N)
......@@ -819,10 +795,6 @@ func TestEnumeratorPrev(t *testing.T) {
}
}
func BenchmarkSeekSeq1e2(b *testing.B) {
benchmarkSeekSeq(b, 1e2)
}
func BenchmarkSeekSeq1e3(b *testing.B) {
benchmarkSeekSeq(b, 1e3)
}
......@@ -855,10 +827,6 @@ func benchmarkSeekSeq(b *testing.B, n int) {
b.StopTimer()
}
func BenchmarkSeekRnd1e2(b *testing.B) {
benchmarkSeekRnd(b, 1e2)
}
func BenchmarkSeekRnd1e3(b *testing.B) {
benchmarkSeekRnd(b, 1e3)
}
......@@ -894,10 +862,6 @@ func benchmarkSeekRnd(b *testing.B, n int) {
}
}
func BenchmarkNext1e2(b *testing.B) {
benchmarkNext(b, 1e2)
}
func BenchmarkNext1e3(b *testing.B) {
benchmarkNext(b, 1e3)
}
......@@ -940,10 +904,6 @@ func benchmarkNext(b *testing.B, n int) {
}
}
func BenchmarkPrev1e2(b *testing.B) {
benchmarkPrev(b, 1e2)
}
func BenchmarkPrev1e3(b *testing.B) {
benchmarkPrev(b, 1e3)
}
......
......@@ -36,34 +36,46 @@
//
// No other changes to int.go are (strictly) necessary, it compiles just fine.
//
// Running the benchmarks for 1000 keys on a machine with Intel X5450 CPU @ 3
// GHz, Go release 1.3.
// Running the benchmarks for 1000 keys on a machine with Intel i5-4670 CPU @
// 3.4GHz, Go release 1.3.
//
// $ go test -bench 1e3 example/all_test.go example/int.go
// PASS
// BenchmarkSetSeq1e3 10000 263951 ns/op
// BenchmarkGetSeq1e3 10000 154410 ns/op
// BenchmarkSetRnd1e3 5000 392690 ns/op
// BenchmarkGetRnd1e3 10000 181776 ns/op
// BenchmarkDelRnd1e3 5000 323795 ns/op
// BenchmarkSeekSeq1e3 10000 235939 ns/op
// BenchmarkSeekRnd1e3 5000 299997 ns/op
// BenchmarkNext1e3 200000 14202 ns/op
// BenchmarkPrev1e3 200000 13842 ns/op
// ok command-line-arguments 30.620s
// BenchmarkSetSeq1e3 10000 146740 ns/op
// BenchmarkGetSeq1e3 10000 108261 ns/op
// BenchmarkSetRnd1e3 10000 254359 ns/op
// BenchmarkGetRnd1e3 10000 134621 ns/op
// BenchmarkDelRnd1e3 10000 211864 ns/op
// BenchmarkSeekSeq1e3 10000 148628 ns/op
// BenchmarkSeekRnd1e3 10000 215166 ns/op
// BenchmarkNext1e3 200000 9211 ns/op
// BenchmarkPrev1e3 200000 8843 ns/op
// ok command-line-arguments 25.071s
// $
package b
import (
"fmt"
"io"
)
//TODO check vs orig initialize/finalize
const (
kx = 128 // min 2 //TODO benchmark tune this number if using custom key/value type(s).
kd = 64 // min 1 //TODO benchmark tune this number if using custom key/value type(s).
kx = 32 //TODO benchmark tune this number if using custom key/value type(s).
kd = 32 //TODO benchmark tune this number if using custom key/value type(s).
)
func init() {
if kd < 1 {
panic(fmt.Errorf("kd %d: out of range", kd))
}
if kx < 2 {
panic(fmt.Errorf("kx %d: out of range", kx))
}
}
type (
// Cmp compares a and b. Return value is:
//
......@@ -529,6 +541,11 @@ func (t *Tree) Set(k interface{} /*K*/, v interface{} /*V*/) {
if ok {
switch x := q.(type) {
case *x:
if x.c > 2*kx {
t.splitX(p, &x, pi, &i)
}
pi = i + 1
p = x
q = x.x[i+1].ch
continue
case *d:
......@@ -580,6 +597,11 @@ func (t *Tree) Put(k interface{} /*K*/, upd func(oldV interface{} /*V*/, exists
if ok {
switch x := q.(type) {
case *x:
if x.c > 2*kx {
t.splitX(p, &x, pi, &i)
}
pi = i + 1
p = x
q = x.x[i+1].ch
continue
case *d:
......
......@@ -2,68 +2,31 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Package b implements a B+tree.
//
// Changelog
//
// 2014-04-18: Added new method Put.
//
// Generic types
//
// Keys and their associated values are interface{} typed, similar to all of
// the containers in the standard library.
//
// Semiautomatic production of a type specific variant of this package is
// supported via
//
// $ make generic
//
// This command will write to stdout a version of the btree.go file where
// every key type occurrence is replaced by the word 'key' (written in all
// CAPS) and every value type occurrence is replaced by the word 'value'
// (written in all CAPS). Then you have to replace these tokens 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.
//
// Running the benchmarks for 1000 keys on a machine with Intel X5450 CPU @ 3
// GHz, Go release 1.3.
//
// $ go test -bench 1e3 example/all_test.go example/int.go
// PASS
// BenchmarkSetSeq1e3 10000 263951 ns/op
// BenchmarkGetSeq1e3 10000 154410 ns/op
// BenchmarkSetRnd1e3 5000 392690 ns/op
// BenchmarkGetRnd1e3 10000 181776 ns/op
// BenchmarkDelRnd1e3 5000 323795 ns/op
// BenchmarkSeekSeq1e3 10000 235939 ns/op
// BenchmarkSeekRnd1e3 5000 299997 ns/op
// BenchmarkNext1e3 200000 14202 ns/op
// BenchmarkPrev1e3 200000 13842 ns/op
// ok command-line-arguments 30.620s
// Package b implements a int->int B+tree.
package b
import (
"fmt"
"io"
)
//TODO check vs orig initialize/finalize
const (
kx = 128 // min 2 //TODO benchmark tune this number if using custom key/value type(s).
kd = 64 // min 1 //TODO benchmark tune this number if using custom key/value type(s).
kx = 32 //TODO benchmark tune this number if using custom key/value type(s).
kd = 32 //TODO benchmark tune this number if using custom key/value type(s).
)
func init() {
if kd < 1 {
panic(fmt.Errorf("kd %d: out of range", kd))
}
if kx < 2 {
panic(fmt.Errorf("kx %d: out of range", kx))
}
}
type (
// Cmp compares a and b. Return value is:
//
......@@ -363,15 +326,15 @@ func (t *Tree) find(q interface{}, k int) (i int, ok bool) {
return l, false
}
//A // First returns the first item of the tree in the key collating order, or
//A // (zero-value, zero-value) if the tree is empty.
//A func (t *Tree) First() (k int, v int) {
//A if q := t.first; q != nil {
//A q := &q.d[0]
//A k, v = q.k, q.v
//A }
//A return
//A }
// First returns the first item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func (t *Tree) First() (k int, v int) {
if q := t.first; q != nil {
q := &q.d[0]
k, v = q.k, q.v
}
return
}
// Get returns the value associated with k and true if it exists. Otherwise Get
// returns (zero-value, false).
......@@ -414,15 +377,15 @@ func (t *Tree) insert(q *d, i int, k int, v int) *d {
return q
}
//A // Last returns the last item of the tree in the key collating order, or
//A // (zero-value, zero-value) if the tree is empty.
//A func (t *Tree) Last() (k int, v int) {
//A if q := t.last; q != nil {
//A q := &q.d[q.c-1]
//A k, v = q.k, q.v
//A }
//A return
//A }
// Last returns the last item of the tree in the key collating order, or
// (zero-value, zero-value) if the tree is empty.
func (t *Tree) Last() (k int, v int) {
if q := t.last; q != nil {
q := &q.d[q.c-1]
k, v = q.k, q.v
}
return
}
// Len returns the number of items in the tree.
func (t *Tree) Len() int {
......@@ -529,6 +492,11 @@ func (t *Tree) Set(k int, v int) {
if ok {
switch x := q.(type) {
case *x:
if x.c > 2*kx {
t.splitX(p, &x, pi, &i)
}
pi = i + 1
p = x
q = x.x[i+1].ch
continue
case *d:
......@@ -580,6 +548,11 @@ func (t *Tree) Put(k int, upd func(oldV int, exists bool) (newV int, write bool)
if ok {
switch x := q.(type) {
case *x:
if x.c > 2*kx {
t.splitX(p, &x, pi, &i)
}
pi = i + 1
p = x
q = x.x[i+1].ch
continue
case *d:
......
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