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

Fix missed splits

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