1
// Copyright 2014 Google Inc.
3
// Licensed under the Apache License, Version 2.0 (the "License");
4
// you may not use this file except in compliance with the License.
5
// You may obtain a copy of the License at
7
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
29
seed := time.Now().Unix()
34
// perm returns a random permutation of n Int items in the range [0, n).
35
func perm(n int) (out []Item) {
36
for _, v := range rand.Perm(n) {
37
out = append(out, Int(v))
42
// rang returns an ordered list of Int items in the range [0, n).
43
func rang(n int) (out []Item) {
44
for i := 0; i < n; i++ {
45
out = append(out, Int(i))
50
// all extracts all items from a tree in order as a slice.
51
func all(t *BTree) (out []Item) {
52
t.Ascend(func(a Item) bool {
59
// rangerev returns a reversed ordered list of Int items in the range [0, n).
60
func rangrev(n int) (out []Item) {
61
for i := n - 1; i >= 0; i-- {
62
out = append(out, Int(i))
67
// allrev extracts all items from a tree in reverse order as a slice.
68
func allrev(t *BTree) (out []Item) {
69
t.Descend(func(a Item) bool {
76
var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
78
func TestBTree(t *testing.T) {
79
tr := New(*btreeDegree)
80
const treeSize = 10000
81
for i := 0; i < 10; i++ {
82
if min := tr.Min(); min != nil {
83
t.Fatalf("empty min, got %+v", min)
85
if max := tr.Max(); max != nil {
86
t.Fatalf("empty max, got %+v", max)
88
for _, item := range perm(treeSize) {
89
if x := tr.ReplaceOrInsert(item); x != nil {
90
t.Fatal("insert found item", item)
93
for _, item := range perm(treeSize) {
94
if x := tr.ReplaceOrInsert(item); x == nil {
95
t.Fatal("insert didn't find item", item)
98
if min, want := tr.Min(), Item(Int(0)); min != want {
99
t.Fatalf("min: want %+v, got %+v", want, min)
101
if max, want := tr.Max(), Item(Int(treeSize-1)); max != want {
102
t.Fatalf("max: want %+v, got %+v", want, max)
105
want := rang(treeSize)
106
if !reflect.DeepEqual(got, want) {
107
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
111
wantrev := rangrev(treeSize)
112
if !reflect.DeepEqual(gotrev, wantrev) {
113
t.Fatalf("mismatch:\n got: %v\nwant: %v", got, want)
116
for _, item := range perm(treeSize) {
117
if x := tr.Delete(item); x == nil {
118
t.Fatalf("didn't find %v", item)
121
if got = all(tr); len(got) > 0 {
122
t.Fatalf("some left!: %v", got)
128
tr := New(*btreeDegree)
129
for i := Int(0); i < 10; i++ {
130
tr.ReplaceOrInsert(i)
132
fmt.Println("len: ", tr.Len())
133
fmt.Println("get3: ", tr.Get(Int(3)))
134
fmt.Println("get100: ", tr.Get(Int(100)))
135
fmt.Println("del4: ", tr.Delete(Int(4)))
136
fmt.Println("del100: ", tr.Delete(Int(100)))
137
fmt.Println("replace5: ", tr.ReplaceOrInsert(Int(5)))
138
fmt.Println("replace100:", tr.ReplaceOrInsert(Int(100)))
139
fmt.Println("min: ", tr.Min())
140
fmt.Println("delmin: ", tr.DeleteMin())
141
fmt.Println("max: ", tr.Max())
142
fmt.Println("delmax: ", tr.DeleteMax())
143
fmt.Println("len: ", tr.Len())
159
func TestDeleteMin(t *testing.T) {
161
for _, v := range perm(100) {
162
tr.ReplaceOrInsert(v)
165
for v := tr.DeleteMin(); v != nil; v = tr.DeleteMin() {
168
if want := rang(100); !reflect.DeepEqual(got, want) {
169
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
173
func TestDeleteMax(t *testing.T) {
175
for _, v := range perm(100) {
176
tr.ReplaceOrInsert(v)
179
for v := tr.DeleteMax(); v != nil; v = tr.DeleteMax() {
183
for i := 0; i < len(got)/2; i++ {
184
got[i], got[len(got)-i-1] = got[len(got)-i-1], got[i]
186
if want := rang(100); !reflect.DeepEqual(got, want) {
187
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
191
func TestAscendRange(t *testing.T) {
193
for _, v := range perm(100) {
194
tr.ReplaceOrInsert(v)
197
tr.AscendRange(Int(40), Int(60), func(a Item) bool {
201
if want := rang(100)[40:60]; !reflect.DeepEqual(got, want) {
202
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
205
tr.AscendRange(Int(40), Int(60), func(a Item) bool {
212
if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
213
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
217
func TestDescendRange(t *testing.T) {
219
for _, v := range perm(100) {
220
tr.ReplaceOrInsert(v)
223
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
227
if want := rangrev(100)[39:59]; !reflect.DeepEqual(got, want) {
228
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
231
tr.DescendRange(Int(60), Int(40), func(a Item) bool {
238
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
239
t.Fatalf("descendrange:\n got: %v\nwant: %v", got, want)
243
func TestAscendLessThan(t *testing.T) {
244
tr := New(*btreeDegree)
245
for _, v := range perm(100) {
246
tr.ReplaceOrInsert(v)
249
tr.AscendLessThan(Int(60), func(a Item) bool {
253
if want := rang(100)[:60]; !reflect.DeepEqual(got, want) {
254
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
257
tr.AscendLessThan(Int(60), func(a Item) bool {
264
if want := rang(100)[:51]; !reflect.DeepEqual(got, want) {
265
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
269
func TestDescendLessOrEqual(t *testing.T) {
270
tr := New(*btreeDegree)
271
for _, v := range perm(100) {
272
tr.ReplaceOrInsert(v)
275
tr.DescendLessOrEqual(Int(40), func(a Item) bool {
279
if want := rangrev(100)[59:]; !reflect.DeepEqual(got, want) {
280
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
283
tr.DescendLessOrEqual(Int(60), func(a Item) bool {
290
if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
291
t.Fatalf("descendlessorequal:\n got: %v\nwant: %v", got, want)
295
func TestAscendGreaterOrEqual(t *testing.T) {
296
tr := New(*btreeDegree)
297
for _, v := range perm(100) {
298
tr.ReplaceOrInsert(v)
301
tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
305
if want := rang(100)[40:]; !reflect.DeepEqual(got, want) {
306
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
309
tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
316
if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
317
t.Fatalf("ascendrange:\n got: %v\nwant: %v", got, want)
321
func TestDescendGreaterThan(t *testing.T) {
322
tr := New(*btreeDegree)
323
for _, v := range perm(100) {
324
tr.ReplaceOrInsert(v)
327
tr.DescendGreaterThan(Int(40), func(a Item) bool {
331
if want := rangrev(100)[:59]; !reflect.DeepEqual(got, want) {
332
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
335
tr.DescendGreaterThan(Int(40), func(a Item) bool {
342
if want := rangrev(100)[:50]; !reflect.DeepEqual(got, want) {
343
t.Fatalf("descendgreaterthan:\n got: %v\nwant: %v", got, want)
347
const benchmarkTreeSize = 10000
349
func BenchmarkInsert(b *testing.B) {
351
insertP := perm(benchmarkTreeSize)
355
tr := New(*btreeDegree)
356
for _, item := range insertP {
357
tr.ReplaceOrInsert(item)
366
func BenchmarkSeek(b *testing.B) {
369
insertP := perm(size)
370
tr := New(*btreeDegree)
371
for _, item := range insertP {
372
tr.ReplaceOrInsert(item)
376
for i := 0; i < b.N; i++ {
377
tr.AscendGreaterOrEqual(Int(i%size), func(i Item) bool { return false })
381
func BenchmarkDeleteInsert(b *testing.B) {
383
insertP := perm(benchmarkTreeSize)
384
tr := New(*btreeDegree)
385
for _, item := range insertP {
386
tr.ReplaceOrInsert(item)
389
for i := 0; i < b.N; i++ {
390
tr.Delete(insertP[i%benchmarkTreeSize])
391
tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
395
func BenchmarkDeleteInsertCloneOnce(b *testing.B) {
397
insertP := perm(benchmarkTreeSize)
398
tr := New(*btreeDegree)
399
for _, item := range insertP {
400
tr.ReplaceOrInsert(item)
404
for i := 0; i < b.N; i++ {
405
tr.Delete(insertP[i%benchmarkTreeSize])
406
tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
410
func BenchmarkDeleteInsertCloneEachTime(b *testing.B) {
412
insertP := perm(benchmarkTreeSize)
413
tr := New(*btreeDegree)
414
for _, item := range insertP {
415
tr.ReplaceOrInsert(item)
418
for i := 0; i < b.N; i++ {
420
tr.Delete(insertP[i%benchmarkTreeSize])
421
tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
425
func BenchmarkDelete(b *testing.B) {
427
insertP := perm(benchmarkTreeSize)
428
removeP := perm(benchmarkTreeSize)
433
tr := New(*btreeDegree)
434
for _, v := range insertP {
435
tr.ReplaceOrInsert(v)
438
for _, item := range removeP {
451
func BenchmarkGet(b *testing.B) {
453
insertP := perm(benchmarkTreeSize)
454
removeP := perm(benchmarkTreeSize)
459
tr := New(*btreeDegree)
460
for _, v := range insertP {
461
tr.ReplaceOrInsert(v)
464
for _, item := range removeP {
474
func BenchmarkGetCloneEachTime(b *testing.B) {
476
insertP := perm(benchmarkTreeSize)
477
removeP := perm(benchmarkTreeSize)
482
tr := New(*btreeDegree)
483
for _, v := range insertP {
484
tr.ReplaceOrInsert(v)
487
for _, item := range removeP {
500
func (a byInts) Len() int {
504
func (a byInts) Less(i, j int) bool {
505
return a[i].(Int) < a[j].(Int)
508
func (a byInts) Swap(i, j int) {
509
a[i], a[j] = a[j], a[i]
512
func BenchmarkAscend(b *testing.B) {
513
arr := perm(benchmarkTreeSize)
514
tr := New(*btreeDegree)
515
for _, v := range arr {
516
tr.ReplaceOrInsert(v)
518
sort.Sort(byInts(arr))
520
for i := 0; i < b.N; i++ {
522
tr.Ascend(func(item Item) bool {
523
if item.(Int) != arr[j].(Int) {
524
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
532
func BenchmarkDescend(b *testing.B) {
533
arr := perm(benchmarkTreeSize)
534
tr := New(*btreeDegree)
535
for _, v := range arr {
536
tr.ReplaceOrInsert(v)
538
sort.Sort(byInts(arr))
540
for i := 0; i < b.N; i++ {
542
tr.Descend(func(item Item) bool {
543
if item.(Int) != arr[j].(Int) {
544
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
552
func BenchmarkAscendRange(b *testing.B) {
553
arr := perm(benchmarkTreeSize)
554
tr := New(*btreeDegree)
555
for _, v := range arr {
556
tr.ReplaceOrInsert(v)
558
sort.Sort(byInts(arr))
560
for i := 0; i < b.N; i++ {
562
tr.AscendRange(Int(100), arr[len(arr)-100], func(item Item) bool {
563
if item.(Int) != arr[j].(Int) {
564
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
569
if j != len(arr)-100 {
570
b.Fatalf("expected: %v, got %v", len(arr)-100, j)
575
func BenchmarkDescendRange(b *testing.B) {
576
arr := perm(benchmarkTreeSize)
577
tr := New(*btreeDegree)
578
for _, v := range arr {
579
tr.ReplaceOrInsert(v)
581
sort.Sort(byInts(arr))
583
for i := 0; i < b.N; i++ {
585
tr.DescendRange(arr[len(arr)-100], Int(100), func(item Item) bool {
586
if item.(Int) != arr[j].(Int) {
587
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
593
b.Fatalf("expected: %v, got %v", len(arr)-100, j)
598
func BenchmarkAscendGreaterOrEqual(b *testing.B) {
599
arr := perm(benchmarkTreeSize)
600
tr := New(*btreeDegree)
601
for _, v := range arr {
602
tr.ReplaceOrInsert(v)
604
sort.Sort(byInts(arr))
606
for i := 0; i < b.N; i++ {
609
tr.AscendGreaterOrEqual(Int(100), func(item Item) bool {
610
if item.(Int) != arr[j].(Int) {
611
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
618
b.Fatalf("expected: %v, got %v", len(arr), j)
620
if k != len(arr)-100 {
621
b.Fatalf("expected: %v, got %v", len(arr)-100, k)
626
func BenchmarkDescendLessOrEqual(b *testing.B) {
627
arr := perm(benchmarkTreeSize)
628
tr := New(*btreeDegree)
629
for _, v := range arr {
630
tr.ReplaceOrInsert(v)
632
sort.Sort(byInts(arr))
634
for i := 0; i < b.N; i++ {
637
tr.DescendLessOrEqual(arr[len(arr)-100], func(item Item) bool {
638
if item.(Int) != arr[j].(Int) {
639
b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
646
b.Fatalf("expected: %v, got %v", -1, j)
649
b.Fatalf("expected: %v, got %v", 99, k)
654
const cloneTestSize = 10000
656
func cloneTest(t *testing.T, b *BTree, start int, p []Item, wg *sync.WaitGroup, trees *[]*BTree) {
657
t.Logf("Starting new clone at %v", start)
658
*trees = append(*trees, b)
659
for i := start; i < cloneTestSize; i++ {
660
b.ReplaceOrInsert(p[i])
661
if i%(cloneTestSize/5) == 0 {
663
go cloneTest(t, b.Clone(), i+1, p, wg, trees)
669
func TestCloneConcurrentOperations(t *testing.T) {
670
b := New(*btreeDegree)
672
p := perm(cloneTestSize)
673
var wg sync.WaitGroup
675
go cloneTest(t, b, 0, p, &wg, &trees)
677
want := rang(cloneTestSize)
678
t.Logf("Starting equality checks on %d trees", len(trees))
679
for i, tree := range trees {
680
if !reflect.DeepEqual(want, all(tree)) {
681
t.Errorf("tree %v mismatch", i)
684
t.Log("Removing half from first half")
685
toRemove := rang(cloneTestSize)[cloneTestSize/2:]
686
for i := 0; i < len(trees)/2; i++ {
690
for _, item := range toRemove {
697
t.Log("Checking all values again")
698
for i, tree := range trees {
700
if i < len(trees)/2 {
701
wantpart = want[:cloneTestSize/2]
705
if got := all(tree); !reflect.DeepEqual(wantpart, got) {
706
t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got))
711
func BenchmarkDeleteAndRestore(b *testing.B) {
714
b.Run(`CopyBigFreeList`, func(b *testing.B) {
715
fl := NewFreeList(16392)
716
tr := NewWithFreeList(*btreeDegree, fl)
717
for _, v := range items {
718
tr.ReplaceOrInsert(v)
722
for i := 0; i < b.N; i++ {
723
dels := make([]Item, 0, tr.Len())
724
tr.Ascend(ItemIterator(func(b Item) bool {
725
dels = append(dels, b)
728
for _, del := range dels {
731
// tr is now empty, we make a new empty copy of it.
732
tr = NewWithFreeList(*btreeDegree, fl)
733
for _, v := range items {
734
tr.ReplaceOrInsert(v)
738
b.Run(`Copy`, func(b *testing.B) {
739
tr := New(*btreeDegree)
740
for _, v := range items {
741
tr.ReplaceOrInsert(v)
745
for i := 0; i < b.N; i++ {
746
dels := make([]Item, 0, tr.Len())
747
tr.Ascend(ItemIterator(func(b Item) bool {
748
dels = append(dels, b)
751
for _, del := range dels {
754
// tr is now empty, we make a new empty copy of it.
755
tr = New(*btreeDegree)
756
for _, v := range items {
757
tr.ReplaceOrInsert(v)
761
b.Run(`ClearBigFreelist`, func(b *testing.B) {
762
fl := NewFreeList(16392)
763
tr := NewWithFreeList(*btreeDegree, fl)
764
for _, v := range items {
765
tr.ReplaceOrInsert(v)
769
for i := 0; i < b.N; i++ {
771
for _, v := range items {
772
tr.ReplaceOrInsert(v)
776
b.Run(`Clear`, func(b *testing.B) {
777
tr := New(*btreeDegree)
778
for _, v := range items {
779
tr.ReplaceOrInsert(v)
783
for i := 0; i < b.N; i++ {
785
for _, v := range items {
786
tr.ReplaceOrInsert(v)