replaced vendor btree with custom version

This commit is contained in:
Josh Baker 2016-07-09 19:43:52 -07:00
parent 8ad3720a79
commit bfa204067c
6 changed files with 252 additions and 79 deletions

View File

@ -2,7 +2,7 @@
![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master) ![Travis CI Build Status](https://api.travis-ci.org/google/btree.svg?branch=master)
This package provides an in-memory B-Tree implementation for Go, useful as a This package provides an in-memory B-Tree implementation for Go, useful as
an ordered, mutable data structure. an ordered, mutable data structure.
The API is based off of the wonderful The API is based off of the wonderful

View File

@ -44,7 +44,7 @@
// widely used ordered tree implementation in the Go ecosystem currently. // widely used ordered tree implementation in the Go ecosystem currently.
// Its functions, therefore, exactly mirror those of // Its functions, therefore, exactly mirror those of
// llrb.LLRB where possible. Unlike gollrb, though, we currently don't // llrb.LLRB where possible. Unlike gollrb, though, we currently don't
// support storing multiple equivalent values or backwards iteration. // support storing multiple equivalent values.
package btree package btree
import ( import (
@ -61,7 +61,10 @@ type Item interface {
// This must provide a strict weak ordering. // This must provide a strict weak ordering.
// If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only // If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only
// hold one of either a or b in the tree). // hold one of either a or b in the tree).
Less(than Item) bool //
// There is a user-defined ctx argument that is equal to the ctx value which
// is set at time of the btree contruction.
Less(than Item, ctx int) bool
} }
const ( const (
@ -106,18 +109,20 @@ type ItemIterator func(i Item) bool
// //
// New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items // New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items
// and 2-4 children). // and 2-4 children).
func New(degree int) *BTree { // The ctx param is user-defined.
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize)) func New(degree, ctx int) *BTree {
return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize), ctx)
} }
// NewWithFreeList creates a new B-Tree that uses the given node free list. // NewWithFreeList creates a new B-Tree that uses the given node free list.
func NewWithFreeList(degree int, f *FreeList) *BTree { func NewWithFreeList(degree int, f *FreeList, ctx int) *BTree {
if degree <= 1 { if degree <= 1 {
panic("bad degree") panic("bad degree")
} }
return &BTree{ return &BTree{
degree: degree, degree: degree,
freelist: f, freelist: f,
ctx: ctx,
} }
} }
@ -156,11 +161,11 @@ func (s *items) pop() (out Item) {
// find returns the index where the given item should be inserted into this // find returns the index where the given item should be inserted into this
// list. 'found' is true if the item already exists in the list at the given // list. 'found' is true if the item already exists in the list at the given
// index. // index.
func (s items) find(item Item) (index int, found bool) { func (s items) find(item Item, ctx int) (index int, found bool) {
i := sort.Search(len(s), func(i int) bool { i := sort.Search(len(s), func(i int) bool {
return item.Less(s[i]) return item.Less(s[i], ctx)
}) })
if i > 0 && !s[i-1].Less(item) { if i > 0 && !s[i-1].Less(item, ctx) {
return i - 1, true return i - 1, true
} }
return i, false return i, false
@ -240,8 +245,8 @@ func (n *node) maybeSplitChild(i, maxItems int) bool {
// insert inserts an item into the subtree rooted at this node, making sure // insert inserts an item into the subtree rooted at this node, making sure
// no nodes in the subtree exceed maxItems items. Should an equivalent item be // no nodes in the subtree exceed maxItems items. Should an equivalent item be
// be found/replaced by insert, it will be returned. // be found/replaced by insert, it will be returned.
func (n *node) insert(item Item, maxItems int) Item { func (n *node) insert(item Item, maxItems int, ctx int) Item {
i, found := n.items.find(item) i, found := n.items.find(item, ctx)
if found { if found {
out := n.items[i] out := n.items[i]
n.items[i] = item n.items[i] = item
@ -254,9 +259,9 @@ func (n *node) insert(item Item, maxItems int) Item {
if n.maybeSplitChild(i, maxItems) { if n.maybeSplitChild(i, maxItems) {
inTree := n.items[i] inTree := n.items[i]
switch { switch {
case item.Less(inTree): case item.Less(inTree, ctx):
// no change, we want first split node // no change, we want first split node
case inTree.Less(item): case inTree.Less(item, ctx):
i++ // we want second split node i++ // we want second split node
default: default:
out := n.items[i] out := n.items[i]
@ -264,16 +269,16 @@ func (n *node) insert(item Item, maxItems int) Item {
return out return out
} }
} }
return n.children[i].insert(item, maxItems) return n.children[i].insert(item, maxItems, ctx)
} }
// get finds the given key in the subtree and returns it. // get finds the given key in the subtree and returns it.
func (n *node) get(key Item) Item { func (n *node) get(key Item, ctx int) Item {
i, found := n.items.find(key) i, found := n.items.find(key, ctx)
if found { if found {
return n.items[i] return n.items[i]
} else if len(n.children) > 0 { } else if len(n.children) > 0 {
return n.children[i].get(key) return n.children[i].get(key, ctx)
} }
return nil return nil
} }
@ -316,7 +321,7 @@ const (
) )
// remove removes an item from the subtree rooted at this node. // remove removes an item from the subtree rooted at this node.
func (n *node) remove(item Item, minItems int, typ toRemove) Item { func (n *node) remove(item Item, minItems int, typ toRemove, ctx int) Item {
var i int var i int
var found bool var found bool
switch typ { switch typ {
@ -331,7 +336,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
} }
i = 0 i = 0
case removeItem: case removeItem:
i, found = n.items.find(item) i, found = n.items.find(item, ctx)
if len(n.children) == 0 { if len(n.children) == 0 {
if found { if found {
return n.items.removeAt(i) return n.items.removeAt(i)
@ -344,7 +349,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
// If we get to here, we have children. // If we get to here, we have children.
child := n.children[i] child := n.children[i]
if len(child.items) <= minItems { if len(child.items) <= minItems {
return n.growChildAndRemove(i, item, minItems, typ) return n.growChildAndRemove(i, item, minItems, typ, ctx)
} }
// Either we had enough items to begin with, or we've done some // Either we had enough items to begin with, or we've done some
// merging/stealing, because we've got enough now and we're ready to return // merging/stealing, because we've got enough now and we're ready to return
@ -356,12 +361,12 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
// We use our special-case 'remove' call with typ=maxItem to pull the // We use our special-case 'remove' call with typ=maxItem to pull the
// predecessor of item i (the rightmost leaf of our immediate left child) // predecessor of item i (the rightmost leaf of our immediate left child)
// and set it into where we pulled the item from. // and set it into where we pulled the item from.
n.items[i] = child.remove(nil, minItems, removeMax) n.items[i] = child.remove(nil, minItems, removeMax, ctx)
return out return out
} }
// Final recursive call. Once we're here, we know that the item isn't in this // Final recursive call. Once we're here, we know that the item isn't in this
// node and that the child is big enough to remove from. // node and that the child is big enough to remove from.
return child.remove(item, minItems, typ) return child.remove(item, minItems, typ, ctx)
} }
// growChildAndRemove grows child 'i' to make sure it's possible to remove an // growChildAndRemove grows child 'i' to make sure it's possible to remove an
@ -383,7 +388,7 @@ func (n *node) remove(item Item, minItems int, typ toRemove) Item {
// We then simply redo our remove call, and the second time (regardless of // We then simply redo our remove call, and the second time (regardless of
// whether we're in case 1 or 2), we'll have enough items and can guarantee // whether we're in case 1 or 2), we'll have enough items and can guarantee
// that we hit case A. // that we hit case A.
func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item { func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove, ctx int) Item {
child := n.children[i] child := n.children[i]
if i > 0 && len(n.children[i-1].items) > minItems { if i > 0 && len(n.children[i-1].items) > minItems {
// Steal from left child // Steal from left child
@ -416,37 +421,80 @@ func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove)
child.children = append(child.children, mergeChild.children...) child.children = append(child.children, mergeChild.children...)
n.t.freeNode(mergeChild) n.t.freeNode(mergeChild)
} }
return n.remove(item, minItems, typ) return n.remove(item, minItems, typ, ctx)
} }
type direction int
const (
descend = direction(-1)
ascend = direction(+1)
)
// iterate provides a simple method for iterating over elements in the tree. // iterate provides a simple method for iterating over elements in the tree.
// It could probably use some work to be extra-efficient (it calls from() a
// little more than it should), but it works pretty well for now.
// //
// It requires that 'from' and 'to' both return true for values we should hit // When ascending, the 'start' should be less than 'stop' and when descending,
// with the iterator. It should also be the case that 'from' returns true for // the 'start' should be greater than 'stop'. Setting 'includeStart' to true
// values less than or equal to values 'to' returns true for, and 'to' // will force the iterator to include the first item when it equals 'start',
// returns true for values greater than or equal to those that 'from' // thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a
// does. // "greaterThan" or "lessThan" queries.
func (n *node) iterate(from, to func(Item) bool, iter ItemIterator) bool { func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator, ctx int) (bool, bool) {
for i, item := range n.items { var ok bool
if !from(item) { switch dir {
case ascend:
for i := 0; i < len(n.items); i++ {
if start != nil && n.items[i].Less(start, ctx) {
continue continue
} }
if len(n.children) > 0 && !n.children[i].iterate(from, to, iter) { if len(n.children) > 0 {
return false if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
return hit, false
} }
if !to(item) {
return false
} }
if !iter(item) { if !includeStart && !hit && start != nil && !start.Less(n.items[i], ctx) {
return false hit = true
continue
}
hit = true
if stop != nil && !n.items[i].Less(stop, ctx) {
return hit, false
}
if !iter(n.items[i]) {
return hit, false
} }
} }
if len(n.children) > 0 { if len(n.children) > 0 {
return n.children[len(n.children)-1].iterate(from, to, iter) if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
return hit, false
} }
return true }
case descend:
for i := len(n.items) - 1; i >= 0; i-- {
if start != nil && !n.items[i].Less(start, ctx) {
if !includeStart || hit || start.Less(n.items[i], ctx) {
continue
}
}
if len(n.children) > 0 {
if hit, ok = n.children[i+1].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
return hit, false
}
}
if stop != nil && !stop.Less(n.items[i], ctx) {
return hit, false // continue
}
hit = true
if !iter(n.items[i]) {
return hit, false
}
}
if len(n.children) > 0 {
if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter, ctx); !ok {
return hit, false
}
}
}
return hit, true
} }
// Used for testing/debugging purposes. // Used for testing/debugging purposes.
@ -469,6 +517,7 @@ type BTree struct {
length int length int
root *node root *node
freelist *FreeList freelist *FreeList
ctx int
} }
// maxItems returns the max number of items to allow per node. // maxItems returns the max number of items to allow per node.
@ -522,7 +571,7 @@ func (t *BTree) ReplaceOrInsert(item Item) Item {
t.root.items = append(t.root.items, item2) t.root.items = append(t.root.items, item2)
t.root.children = append(t.root.children, oldroot, second) t.root.children = append(t.root.children, oldroot, second)
} }
out := t.root.insert(item, t.maxItems()) out := t.root.insert(item, t.maxItems(), t.ctx)
if out == nil { if out == nil {
t.length++ t.length++
} }
@ -532,26 +581,26 @@ func (t *BTree) ReplaceOrInsert(item Item) Item {
// Delete removes an item equal to the passed in item from the tree, returning // Delete removes an item equal to the passed in item from the tree, returning
// it. If no such item exists, returns nil. // it. If no such item exists, returns nil.
func (t *BTree) Delete(item Item) Item { func (t *BTree) Delete(item Item) Item {
return t.deleteItem(item, removeItem) return t.deleteItem(item, removeItem, t.ctx)
} }
// DeleteMin removes the smallest item in the tree and returns it. // DeleteMin removes the smallest item in the tree and returns it.
// If no such item exists, returns nil. // If no such item exists, returns nil.
func (t *BTree) DeleteMin() Item { func (t *BTree) DeleteMin() Item {
return t.deleteItem(nil, removeMin) return t.deleteItem(nil, removeMin, t.ctx)
} }
// DeleteMax removes the largest item in the tree and returns it. // DeleteMax removes the largest item in the tree and returns it.
// If no such item exists, returns nil. // If no such item exists, returns nil.
func (t *BTree) DeleteMax() Item { func (t *BTree) DeleteMax() Item {
return t.deleteItem(nil, removeMax) return t.deleteItem(nil, removeMax, t.ctx)
} }
func (t *BTree) deleteItem(item Item, typ toRemove) Item { func (t *BTree) deleteItem(item Item, typ toRemove, ctx int) Item {
if t.root == nil || len(t.root.items) == 0 { if t.root == nil || len(t.root.items) == 0 {
return nil return nil
} }
out := t.root.remove(item, t.minItems(), typ) out := t.root.remove(item, t.minItems(), typ, ctx)
if len(t.root.items) == 0 && len(t.root.children) > 0 { if len(t.root.items) == 0 && len(t.root.children) > 0 {
oldroot := t.root oldroot := t.root
t.root = t.root.children[0] t.root = t.root.children[0]
@ -569,10 +618,7 @@ func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator
if t.root == nil { if t.root == nil {
return return
} }
t.root.iterate( t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator, t.ctx)
func(a Item) bool { return !a.Less(greaterOrEqual) },
func(a Item) bool { return a.Less(lessThan) },
iterator)
} }
// AscendLessThan calls the iterator for every value in the tree within the range // AscendLessThan calls the iterator for every value in the tree within the range
@ -581,10 +627,7 @@ func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) {
if t.root == nil { if t.root == nil {
return return
} }
t.root.iterate( t.root.iterate(ascend, nil, pivot, false, false, iterator, t.ctx)
func(a Item) bool { return true },
func(a Item) bool { return a.Less(pivot) },
iterator)
} }
// AscendGreaterOrEqual calls the iterator for every value in the tree within // AscendGreaterOrEqual calls the iterator for every value in the tree within
@ -593,10 +636,7 @@ func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) {
if t.root == nil { if t.root == nil {
return return
} }
t.root.iterate( t.root.iterate(ascend, pivot, nil, true, false, iterator, t.ctx)
func(a Item) bool { return !a.Less(pivot) },
func(a Item) bool { return true },
iterator)
} }
// Ascend calls the iterator for every value in the tree within the range // Ascend calls the iterator for every value in the tree within the range
@ -605,10 +645,43 @@ func (t *BTree) Ascend(iterator ItemIterator) {
if t.root == nil { if t.root == nil {
return return
} }
t.root.iterate( t.root.iterate(ascend, nil, nil, false, false, iterator, t.ctx)
func(a Item) bool { return true }, }
func(a Item) bool { return true },
iterator) // DescendRange calls the iterator for every value in the tree within the range
// [lessOrEqual, greaterThan), until iterator returns false.
func (t *BTree) DescendRange(lessOrEqual, greaterThan Item, iterator ItemIterator) {
if t.root == nil {
return
}
t.root.iterate(descend, lessOrEqual, greaterThan, true, false, iterator, t.ctx)
}
// DescendLessOrEqual calls the iterator for every value in the tree within the range
// [pivot, first], until iterator returns false.
func (t *BTree) DescendLessOrEqual(pivot Item, iterator ItemIterator) {
if t.root == nil {
return
}
t.root.iterate(descend, pivot, nil, true, false, iterator, t.ctx)
}
// DescendGreaterThan calls the iterator for every value in the tree within
// the range [last, pivot), until iterator returns false.
func (t *BTree) DescendGreaterThan(pivot Item, iterator ItemIterator) {
if t.root == nil {
return
}
t.root.iterate(descend, nil, pivot, false, false, iterator, t.ctx)
}
// Descend calls the iterator for every value in the tree within the range
// [last, first], until iterator returns false.
func (t *BTree) Descend(iterator ItemIterator) {
if t.root == nil {
return
}
t.root.iterate(descend, nil, nil, false, false, iterator, t.ctx)
} }
// Get looks for the key item in the tree, returning it. It returns nil if // Get looks for the key item in the tree, returning it. It returns nil if
@ -617,7 +690,7 @@ func (t *BTree) Get(key Item) Item {
if t.root == nil { if t.root == nil {
return nil return nil
} }
return t.root.get(key) return t.root.get(key, t.ctx)
} }
// Min returns the smallest item in the tree, or nil if the tree is empty. // Min returns the smallest item in the tree, or nil if the tree is empty.
@ -644,6 +717,6 @@ func (t *BTree) Len() int {
type Int int type Int int
// Less returns true if int(a) < int(b). // Less returns true if int(a) < int(b).
func (a Int) Less(b Item) bool { func (a Int) Less(b Item, ctx int) bool {
return a < b.(Int) return a < b.(Int)
} }

View File

@ -54,10 +54,27 @@ func all(t *BTree) (out []Item) {
return return
} }
// rangerev returns a reversed ordered list of Int items in the range [0, n).
func rangrev(n int) (out []Item) {
for i := n - 1; i >= 0; i-- {
out = append(out, Int(i))
}
return
}
// allrev extracts all items from a tree in reverse order as a slice.
func allrev(t *BTree) (out []Item) {
t.Descend(func(a Item) bool {
out = append(out, a)
return true
})
return
}
var btreeDegree = flag.Int("degree", 32, "B-Tree degree") var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
func TestBTree(t *testing.T) { func TestBTree(t *testing.T) {
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
const treeSize = 10000 const treeSize = 10000
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
if min := tr.Min(); min != nil { if min := tr.Min(); min != nil {
@ -87,6 +104,13 @@ func TestBTree(t *testing.T) {
if !reflect.DeepEqual(got, want) { if !reflect.DeepEqual(got, want) {
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want) t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
} }
gotrev := allrev(tr)
wantrev := rangrev(treeSize)
if !reflect.DeepEqual(gotrev, wantrev) {
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
}
for _, item := range perm(treeSize) { for _, item := range perm(treeSize) {
if x := tr.Delete(item); x == nil { if x := tr.Delete(item); x == nil {
t.Fatalf("didn't find %v", item) t.Fatalf("didn't find %v", item)
@ -99,7 +123,7 @@ func TestBTree(t *testing.T) {
} }
func ExampleBTree() { func ExampleBTree() {
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
for i := Int(0); i < 10; i++ { for i := Int(0); i < 10; i++ {
tr.ReplaceOrInsert(i) tr.ReplaceOrInsert(i)
} }
@ -131,7 +155,7 @@ func ExampleBTree() {
} }
func TestDeleteMin(t *testing.T) { func TestDeleteMin(t *testing.T) {
tr := New(3) tr := New(3, 0)
for _, v := range perm(100) { for _, v := range perm(100) {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }
@ -145,7 +169,7 @@ func TestDeleteMin(t *testing.T) {
} }
func TestDeleteMax(t *testing.T) { func TestDeleteMax(t *testing.T) {
tr := New(3) tr := New(3, 0)
for _, v := range perm(100) { for _, v := range perm(100) {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }
@ -163,7 +187,7 @@ func TestDeleteMax(t *testing.T) {
} }
func TestAscendRange(t *testing.T) { func TestAscendRange(t *testing.T) {
tr := New(2) tr := New(2, 0)
for _, v := range perm(100) { for _, v := range perm(100) {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }
@ -188,8 +212,33 @@ func TestAscendRange(t *testing.T) {
} }
} }
func TestDescendRange(t *testing.T) {
tr := New(2, 0)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rangrev(100)[39:59]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
if a.(Int) < 50 {
return false
}
got = append(got, a)
return true
})
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
}
}
func TestAscendLessThan(t *testing.T) { func TestAscendLessThan(t *testing.T) {
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
for _, v := range perm(100) { for _, v := range perm(100) {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }
@ -214,8 +263,33 @@ func TestAscendLessThan(t *testing.T) {
} }
} }
func TestDescendLessOrEqual(t *testing.T) {
tr := New(*btreeDegree, 0)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.DescendLessOrEqual(Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rangrev(100)[59:]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.DescendLessOrEqual(Int(60), func(a Item) bool {
if a.(Int) < 50 {
return false
}
got = append(got, a)
return true
})
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
}
}
func TestAscendGreaterOrEqual(t *testing.T) { func TestAscendGreaterOrEqual(t *testing.T) {
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
for _, v := range perm(100) { for _, v := range perm(100) {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }
@ -240,6 +314,32 @@ func TestAscendGreaterOrEqual(t *testing.T) {
} }
} }
func TestDescendGreaterThan(t *testing.T) {
tr := New(*btreeDegree, 0)
for _, v := range perm(100) {
tr.ReplaceOrInsert(v)
}
var got []Item
tr.DescendGreaterThan(Int(40), func(a Item) bool {
got = append(got, a)
return true
})
if want := rangrev(100)[:59]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
}
got = got[:0]
tr.DescendGreaterThan(Int(40), func(a Item) bool {
if a.(Int) < 50 {
return false
}
got = append(got, a)
return true
})
if want := rangrev(100)[:50]; !reflect.DeepEqual(got, want) {
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
}
}
const benchmarkTreeSize = 10000 const benchmarkTreeSize = 10000
func BenchmarkInsert(b *testing.B) { func BenchmarkInsert(b *testing.B) {
@ -248,7 +348,7 @@ func BenchmarkInsert(b *testing.B) {
b.StartTimer() b.StartTimer()
i := 0 i := 0
for i < b.N { for i < b.N {
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
for _, item := range insertP { for _, item := range insertP {
tr.ReplaceOrInsert(item) tr.ReplaceOrInsert(item)
i++ i++
@ -267,7 +367,7 @@ func BenchmarkDelete(b *testing.B) {
i := 0 i := 0
for i < b.N { for i < b.N {
b.StopTimer() b.StopTimer()
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
for _, v := range insertP { for _, v := range insertP {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }
@ -293,7 +393,7 @@ func BenchmarkGet(b *testing.B) {
i := 0 i := 0
for i < b.N { for i < b.N {
b.StopTimer() b.StopTimer()
tr := New(*btreeDegree) tr := New(*btreeDegree, 0)
for _, v := range insertP { for _, v := range insertP {
tr.ReplaceOrInsert(v) tr.ReplaceOrInsert(v)
} }