mirror of
https://github.com/featurebasedb/featurebase.git
synced 2026-08-28 02:44:59 +00:00
Merge pull request #1916 from seebs/seebs/btree
improve btree performance a bit, add some testing for it.
This commit is contained in:
commit
80930de295
5 changed files with 1576 additions and 40 deletions
|
|
@ -38,9 +38,9 @@ import (
|
|||
|
||||
const (
|
||||
// kx must be >= 2
|
||||
kx = 128 //TODO benchmark tune this number if using custom key/value type(s).
|
||||
kx = 126 //TODO benchmark tune this number if using custom key/value type(s).
|
||||
// kd must be >= 1
|
||||
kd = 128 //TODO benchmark tune this number if using custom key/value type(s).
|
||||
kd = 254 //TODO benchmark tune this number if using custom key/value type(s).
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -52,9 +52,8 @@ var (
|
|||
|
||||
type btTpool struct{ sync.Pool }
|
||||
|
||||
func (p *btTpool) get(cmp Cmp) *tree {
|
||||
func (p *btTpool) get() *tree {
|
||||
x := p.Get().(*tree)
|
||||
x.cmp = cmp
|
||||
return x
|
||||
}
|
||||
|
||||
|
|
@ -67,19 +66,12 @@ func (p *btEpool) get(err error, hit bool, i int, k uint64, q *d, t *tree, ver i
|
|||
}
|
||||
|
||||
type (
|
||||
// Cmp compares a and b. Return value is:
|
||||
//
|
||||
// < 0 if a < b
|
||||
// 0 if a == b
|
||||
// > 0 if a > b
|
||||
//
|
||||
Cmp func(a, b uint64) int64
|
||||
|
||||
d struct { // data page
|
||||
c int
|
||||
d [2*kd + 1]de
|
||||
n *d
|
||||
p *d
|
||||
dTree //lint:ignore U1000 this is conditional on a build flag
|
||||
c int
|
||||
d [2*kd + 1]de
|
||||
n *d
|
||||
p *d
|
||||
}
|
||||
|
||||
de struct { // d element
|
||||
|
|
@ -107,12 +99,12 @@ type (
|
|||
|
||||
// tree is a B+tree.
|
||||
tree struct {
|
||||
c int
|
||||
cmp Cmp
|
||||
first *d
|
||||
last *d
|
||||
r interface{}
|
||||
ver int64
|
||||
treeInst //lint:ignore U1000 this is conditional on a build flag
|
||||
c int
|
||||
first *d
|
||||
last *d
|
||||
r interface{}
|
||||
ver int64
|
||||
}
|
||||
|
||||
xe struct { // x element
|
||||
|
|
@ -197,6 +189,7 @@ func (q *x) siblings(i int) (l, r *d) {
|
|||
// -------------------------------------------------------------------------- d
|
||||
|
||||
func (l *d) mvL(r *d, c int) {
|
||||
r.didCopy(r.c)
|
||||
copy(l.d[l.c:], r.d[:c])
|
||||
copy(r.d[:], r.d[c:r.c])
|
||||
// Zero out the de's here to prevent reading bad data
|
||||
|
|
@ -209,6 +202,7 @@ func (l *d) mvL(r *d, c int) {
|
|||
}
|
||||
|
||||
func (l *d) mvR(r *d, c int) {
|
||||
l.didCopy(r.c + c)
|
||||
copy(r.d[c:], r.d[:r.c])
|
||||
copy(r.d[:c], l.d[l.c-c:])
|
||||
// Zero out the de's here to prevent reading bad data
|
||||
|
|
@ -224,8 +218,8 @@ func (l *d) mvR(r *d, c int) {
|
|||
|
||||
// treeNew returns a newly created, empty Tree. The compare function is used
|
||||
// for key collation.
|
||||
func treeNew(cmp Cmp) *tree {
|
||||
return btTPool.get(cmp)
|
||||
func treeNew() *tree {
|
||||
return btTPool.get()
|
||||
}
|
||||
|
||||
// Clear removes all K/V pairs from the tree.
|
||||
|
|
@ -364,6 +358,7 @@ func (t *tree) extract(q *d, i int) { // (r *container) {
|
|||
//r = q.d[i].v // prepared for Extract
|
||||
q.c--
|
||||
if i < q.c {
|
||||
t.didCopy(q.c - i)
|
||||
copy(q.d[i:], q.d[i+1:q.c+1])
|
||||
}
|
||||
q.d[q.c] = zde // GC
|
||||
|
|
@ -379,13 +374,13 @@ func (t *tree) find(q interface{}, k uint64) (i int, ok bool) {
|
|||
for l <= h {
|
||||
m := (l + h) >> 1
|
||||
mk = x.x[m].k
|
||||
switch cmp := t.cmp(k, mk); {
|
||||
case cmp > 0:
|
||||
switch {
|
||||
case k > mk:
|
||||
l = m + 1
|
||||
case cmp == 0:
|
||||
return m, true
|
||||
default:
|
||||
case k < mk:
|
||||
h = m - 1
|
||||
default:
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
case *d:
|
||||
|
|
@ -393,13 +388,13 @@ func (t *tree) find(q interface{}, k uint64) (i int, ok bool) {
|
|||
for l <= h {
|
||||
m := (l + h) >> 1
|
||||
mk = x.d[m].k
|
||||
switch cmp := t.cmp(k, mk); {
|
||||
case cmp > 0:
|
||||
switch {
|
||||
case k > mk:
|
||||
l = m + 1
|
||||
case cmp == 0:
|
||||
return m, true
|
||||
default:
|
||||
case k < mk:
|
||||
h = m - 1
|
||||
default:
|
||||
return m, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -446,8 +441,10 @@ func (t *tree) Get(k uint64) (v *Container, ok bool) {
|
|||
|
||||
func (t *tree) insert(q *d, i int, k uint64, v *Container) *d {
|
||||
t.ver++
|
||||
q.setTree(t)
|
||||
c := q.c
|
||||
if i < c {
|
||||
t.didCopy(c - i)
|
||||
copy(q.d[i+1:], q.d[i:c])
|
||||
}
|
||||
c++
|
||||
|
|
@ -704,6 +701,7 @@ func (t *tree) Put(k uint64, upd func(oldV *Container, exists bool) (newV *Conta
|
|||
func (t *tree) split(p *x, q *d, pi, i int, k uint64, v *Container) {
|
||||
t.ver++
|
||||
r := btDPool.Get().(*d)
|
||||
r.setTree(t)
|
||||
if q.n != nil {
|
||||
r.n = q.n
|
||||
r.n.p = r
|
||||
|
|
@ -713,6 +711,7 @@ func (t *tree) split(p *x, q *d, pi, i int, k uint64, v *Container) {
|
|||
q.n = r
|
||||
r.p = q
|
||||
|
||||
t.didCopy(kd)
|
||||
copy(r.d[:], q.d[kd:2*kd])
|
||||
for i := range q.d[kd:] {
|
||||
q.d[kd+i] = zde
|
||||
|
|
|
|||
1490
roaring/btree_test.go
Normal file
1490
roaring/btree_test.go
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -18,10 +18,6 @@ import (
|
|||
"io"
|
||||
)
|
||||
|
||||
func cmp(a, b uint64) int64 {
|
||||
return int64(a - b)
|
||||
}
|
||||
|
||||
type bTreeContainers struct {
|
||||
tree *tree
|
||||
|
||||
|
|
@ -31,7 +27,7 @@ type bTreeContainers struct {
|
|||
|
||||
func newBTreeContainers() *bTreeContainers {
|
||||
return &bTreeContainers{
|
||||
tree: treeNew(cmp),
|
||||
tree: treeNew(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -158,7 +154,7 @@ func (btc *bTreeContainers) Size() int {
|
|||
}
|
||||
|
||||
func (btc *bTreeContainers) Reset() {
|
||||
btc.tree = treeNew(cmp)
|
||||
btc.tree = treeNew()
|
||||
btc.lastKey = 0
|
||||
btc.lastContainer = nil
|
||||
}
|
||||
|
|
|
|||
27
roaring/inst.go
Normal file
27
roaring/inst.go
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
// +build btreeInstrumentation
|
||||
|
||||
package roaring
|
||||
|
||||
type dTree struct {
|
||||
t *tree
|
||||
}
|
||||
|
||||
type treeInst struct {
|
||||
deCopied int64
|
||||
}
|
||||
|
||||
func (t *tree) didCopy(n int) {
|
||||
t.deCopied += int64(n)
|
||||
}
|
||||
|
||||
func (d *d) didCopy(n int) {
|
||||
d.t.deCopied += int64(n)
|
||||
}
|
||||
|
||||
func (t *tree) countCopies() int64 {
|
||||
return t.deCopied
|
||||
}
|
||||
|
||||
func (d *d) setTree(t *tree) {
|
||||
d.t = t
|
||||
}
|
||||
24
roaring/nop_inst.go
Normal file
24
roaring/nop_inst.go
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
// +build !btreeInstrumentation
|
||||
|
||||
package roaring
|
||||
|
||||
//lint:ignore U1000 this is conditional on a build flag
|
||||
type dTree struct {
|
||||
}
|
||||
|
||||
//lint:ignore U1000 this is conditional on a build flag
|
||||
type treeInst struct {
|
||||
}
|
||||
|
||||
func (t *tree) didCopy(n int) {
|
||||
}
|
||||
|
||||
func (d *d) didCopy(n int) {
|
||||
}
|
||||
|
||||
func (t *tree) countCopies() int64 {
|
||||
return 0
|
||||
}
|
||||
|
||||
func (d *d) setTree(t *tree) {
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue