• 谷歌开源的一个BTREE实现 Go语言


      1 // Copyright 2014 Google Inc.
      2 //
      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
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      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.
     14 
     15 package btree
     16 
     17 import (
     18     "flag"
     19     "fmt"
     20     "math/rand"
     21     "reflect"
     22     "sort"
     23     "sync"
     24     "testing"
     25     "time"
     26 )
     27 
     28 func init() {
     29     seed := time.Now().Unix()
     30     fmt.Println(seed)
     31     rand.Seed(seed)
     32 }
     33 
     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))
     38     }
     39     return
     40 }
     41 
     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))
     46     }
     47     return
     48 }
     49 
     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 {
     53         out = append(out, a)
     54         return true
     55     })
     56     return
     57 }
     58 
     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))
     63     }
     64     return
     65 }
     66 
     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 {
     70         out = append(out, a)
     71         return true
     72     })
     73     return
     74 }
     75 
     76 var btreeDegree = flag.Int("degree", 32, "B-Tree degree")
     77 
     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)
     84         }
     85         if max := tr.Max(); max != nil {
     86             t.Fatalf("empty max, got %+v", max)
     87         }
     88         for _, item := range perm(treeSize) {
     89             if x := tr.ReplaceOrInsert(item); x != nil {
     90                 t.Fatal("insert found item", item)
     91             }
     92         }
     93         for _, item := range perm(treeSize) {
     94             if x := tr.ReplaceOrInsert(item); x == nil {
     95                 t.Fatal("insert didn't find item", item)
     96             }
     97         }
     98         if min, want := tr.Min(), Item(Int(0)); min != want {
     99             t.Fatalf("min: want %+v, got %+v", want, min)
    100         }
    101         if max, want := tr.Max(), Item(Int(treeSize-1)); max != want {
    102             t.Fatalf("max: want %+v, got %+v", want, max)
    103         }
    104         got := all(tr)
    105         want := rang(treeSize)
    106         if !reflect.DeepEqual(got, want) {
    107             t.Fatalf("mismatch:
     got: %v
    want: %v", got, want)
    108         }
    109 
    110         gotrev := allrev(tr)
    111         wantrev := rangrev(treeSize)
    112         if !reflect.DeepEqual(gotrev, wantrev) {
    113             t.Fatalf("mismatch:
     got: %v
    want: %v", got, want)
    114         }
    115 
    116         for _, item := range perm(treeSize) {
    117             if x := tr.Delete(item); x == nil {
    118                 t.Fatalf("didn't find %v", item)
    119             }
    120         }
    121         if got = all(tr); len(got) > 0 {
    122             t.Fatalf("some left!: %v", got)
    123         }
    124     }
    125 }
    126 
    127 func ExampleBTree() {
    128     tr := New(*btreeDegree)
    129     for i := Int(0); i < 10; i++ {
    130         tr.ReplaceOrInsert(i)
    131     }
    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())
    144     // Output:
    145     // len:        10
    146     // get3:       3
    147     // get100:     <nil>
    148     // del4:       4
    149     // del100:     <nil>
    150     // replace5:   5
    151     // replace100: <nil>
    152     // min:        0
    153     // delmin:     0
    154     // max:        100
    155     // delmax:     100
    156     // len:        8
    157 }
    158 
    159 func TestDeleteMin(t *testing.T) {
    160     tr := New(3)
    161     for _, v := range perm(100) {
    162         tr.ReplaceOrInsert(v)
    163     }
    164     var got []Item
    165     for v := tr.DeleteMin(); v != nil; v = tr.DeleteMin() {
    166         got = append(got, v)
    167     }
    168     if want := rang(100); !reflect.DeepEqual(got, want) {
    169         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    170     }
    171 }
    172 
    173 func TestDeleteMax(t *testing.T) {
    174     tr := New(3)
    175     for _, v := range perm(100) {
    176         tr.ReplaceOrInsert(v)
    177     }
    178     var got []Item
    179     for v := tr.DeleteMax(); v != nil; v = tr.DeleteMax() {
    180         got = append(got, v)
    181     }
    182     // Reverse our list.
    183     for i := 0; i < len(got)/2; i++ {
    184         got[i], got[len(got)-i-1] = got[len(got)-i-1], got[i]
    185     }
    186     if want := rang(100); !reflect.DeepEqual(got, want) {
    187         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    188     }
    189 }
    190 
    191 func TestAscendRange(t *testing.T) {
    192     tr := New(2)
    193     for _, v := range perm(100) {
    194         tr.ReplaceOrInsert(v)
    195     }
    196     var got []Item
    197     tr.AscendRange(Int(40), Int(60), func(a Item) bool {
    198         got = append(got, a)
    199         return true
    200     })
    201     if want := rang(100)[40:60]; !reflect.DeepEqual(got, want) {
    202         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    203     }
    204     got = got[:0]
    205     tr.AscendRange(Int(40), Int(60), func(a Item) bool {
    206         if a.(Int) > 50 {
    207             return false
    208         }
    209         got = append(got, a)
    210         return true
    211     })
    212     if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
    213         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    214     }
    215 }
    216 
    217 func TestDescendRange(t *testing.T) {
    218     tr := New(2)
    219     for _, v := range perm(100) {
    220         tr.ReplaceOrInsert(v)
    221     }
    222     var got []Item
    223     tr.DescendRange(Int(60), Int(40), func(a Item) bool {
    224         got = append(got, a)
    225         return true
    226     })
    227     if want := rangrev(100)[39:59]; !reflect.DeepEqual(got, want) {
    228         t.Fatalf("descendrange:
     got: %v
    want: %v", got, want)
    229     }
    230     got = got[:0]
    231     tr.DescendRange(Int(60), Int(40), func(a Item) bool {
    232         if a.(Int) < 50 {
    233             return false
    234         }
    235         got = append(got, a)
    236         return true
    237     })
    238     if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
    239         t.Fatalf("descendrange:
     got: %v
    want: %v", got, want)
    240     }
    241 }
    242 func TestAscendLessThan(t *testing.T) {
    243     tr := New(*btreeDegree)
    244     for _, v := range perm(100) {
    245         tr.ReplaceOrInsert(v)
    246     }
    247     var got []Item
    248     tr.AscendLessThan(Int(60), func(a Item) bool {
    249         got = append(got, a)
    250         return true
    251     })
    252     if want := rang(100)[:60]; !reflect.DeepEqual(got, want) {
    253         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    254     }
    255     got = got[:0]
    256     tr.AscendLessThan(Int(60), func(a Item) bool {
    257         if a.(Int) > 50 {
    258             return false
    259         }
    260         got = append(got, a)
    261         return true
    262     })
    263     if want := rang(100)[:51]; !reflect.DeepEqual(got, want) {
    264         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    265     }
    266 }
    267 
    268 func TestDescendLessOrEqual(t *testing.T) {
    269     tr := New(*btreeDegree)
    270     for _, v := range perm(100) {
    271         tr.ReplaceOrInsert(v)
    272     }
    273     var got []Item
    274     tr.DescendLessOrEqual(Int(40), func(a Item) bool {
    275         got = append(got, a)
    276         return true
    277     })
    278     if want := rangrev(100)[59:]; !reflect.DeepEqual(got, want) {
    279         t.Fatalf("descendlessorequal:
     got: %v
    want: %v", got, want)
    280     }
    281     got = got[:0]
    282     tr.DescendLessOrEqual(Int(60), func(a Item) bool {
    283         if a.(Int) < 50 {
    284             return false
    285         }
    286         got = append(got, a)
    287         return true
    288     })
    289     if want := rangrev(100)[39:50]; !reflect.DeepEqual(got, want) {
    290         t.Fatalf("descendlessorequal:
     got: %v
    want: %v", got, want)
    291     }
    292 }
    293 func TestAscendGreaterOrEqual(t *testing.T) {
    294     tr := New(*btreeDegree)
    295     for _, v := range perm(100) {
    296         tr.ReplaceOrInsert(v)
    297     }
    298     var got []Item
    299     tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
    300         got = append(got, a)
    301         return true
    302     })
    303     if want := rang(100)[40:]; !reflect.DeepEqual(got, want) {
    304         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    305     }
    306     got = got[:0]
    307     tr.AscendGreaterOrEqual(Int(40), func(a Item) bool {
    308         if a.(Int) > 50 {
    309             return false
    310         }
    311         got = append(got, a)
    312         return true
    313     })
    314     if want := rang(100)[40:51]; !reflect.DeepEqual(got, want) {
    315         t.Fatalf("ascendrange:
     got: %v
    want: %v", got, want)
    316     }
    317 }
    318 
    319 func TestDescendGreaterThan(t *testing.T) {
    320     tr := New(*btreeDegree)
    321     for _, v := range perm(100) {
    322         tr.ReplaceOrInsert(v)
    323     }
    324     var got []Item
    325     tr.DescendGreaterThan(Int(40), func(a Item) bool {
    326         got = append(got, a)
    327         return true
    328     })
    329     if want := rangrev(100)[:59]; !reflect.DeepEqual(got, want) {
    330         t.Fatalf("descendgreaterthan:
     got: %v
    want: %v", got, want)
    331     }
    332     got = got[:0]
    333     tr.DescendGreaterThan(Int(40), func(a Item) bool {
    334         if a.(Int) < 50 {
    335             return false
    336         }
    337         got = append(got, a)
    338         return true
    339     })
    340     if want := rangrev(100)[:50]; !reflect.DeepEqual(got, want) {
    341         t.Fatalf("descendgreaterthan:
     got: %v
    want: %v", got, want)
    342     }
    343 }
    344 
    345 const benchmarkTreeSize = 10000
    346 
    347 func BenchmarkInsert(b *testing.B) {
    348     b.StopTimer()
    349     insertP := perm(benchmarkTreeSize)
    350     b.StartTimer()
    351     i := 0
    352     for i < b.N {
    353         tr := New(*btreeDegree)
    354         for _, item := range insertP {
    355             tr.ReplaceOrInsert(item)
    356             i++
    357             if i >= b.N {
    358                 return
    359             }
    360         }
    361     }
    362 }
    363 
    364 func BenchmarkSeek(b *testing.B) {
    365     b.StopTimer()
    366     size := 100000
    367     insertP := perm(size)
    368     tr := New(*btreeDegree)
    369     for _, item := range insertP {
    370         tr.ReplaceOrInsert(item)
    371     }
    372     b.StartTimer()
    373 
    374     for i := 0; i < b.N; i++ {
    375         tr.AscendGreaterOrEqual(Int(i%size), func(i Item) bool { return false })
    376     }
    377 }
    378 
    379 func BenchmarkDeleteInsert(b *testing.B) {
    380     b.StopTimer()
    381     insertP := perm(benchmarkTreeSize)
    382     tr := New(*btreeDegree)
    383     for _, item := range insertP {
    384         tr.ReplaceOrInsert(item)
    385     }
    386     b.StartTimer()
    387     for i := 0; i < b.N; i++ {
    388         tr.Delete(insertP[i%benchmarkTreeSize])
    389         tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
    390     }
    391 }
    392 
    393 func BenchmarkDeleteInsertCloneOnce(b *testing.B) {
    394     b.StopTimer()
    395     insertP := perm(benchmarkTreeSize)
    396     tr := New(*btreeDegree)
    397     for _, item := range insertP {
    398         tr.ReplaceOrInsert(item)
    399     }
    400     tr = tr.Clone()
    401     b.StartTimer()
    402     for i := 0; i < b.N; i++ {
    403         tr.Delete(insertP[i%benchmarkTreeSize])
    404         tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
    405     }
    406 }
    407 
    408 func BenchmarkDeleteInsertCloneEachTime(b *testing.B) {
    409     b.StopTimer()
    410     insertP := perm(benchmarkTreeSize)
    411     tr := New(*btreeDegree)
    412     for _, item := range insertP {
    413         tr.ReplaceOrInsert(item)
    414     }
    415     b.StartTimer()
    416     for i := 0; i < b.N; i++ {
    417         tr = tr.Clone()
    418         tr.Delete(insertP[i%benchmarkTreeSize])
    419         tr.ReplaceOrInsert(insertP[i%benchmarkTreeSize])
    420     }
    421 }
    422 
    423 func BenchmarkDelete(b *testing.B) {
    424     b.StopTimer()
    425     insertP := perm(benchmarkTreeSize)
    426     removeP := perm(benchmarkTreeSize)
    427     b.StartTimer()
    428     i := 0
    429     for i < b.N {
    430         b.StopTimer()
    431         tr := New(*btreeDegree)
    432         for _, v := range insertP {
    433             tr.ReplaceOrInsert(v)
    434         }
    435         b.StartTimer()
    436         for _, item := range removeP {
    437             tr.Delete(item)
    438             i++
    439             if i >= b.N {
    440                 return
    441             }
    442         }
    443         if tr.Len() > 0 {
    444             panic(tr.Len())
    445         }
    446     }
    447 }
    448 
    449 func BenchmarkGet(b *testing.B) {
    450     b.StopTimer()
    451     insertP := perm(benchmarkTreeSize)
    452     removeP := perm(benchmarkTreeSize)
    453     b.StartTimer()
    454     i := 0
    455     for i < b.N {
    456         b.StopTimer()
    457         tr := New(*btreeDegree)
    458         for _, v := range insertP {
    459             tr.ReplaceOrInsert(v)
    460         }
    461         b.StartTimer()
    462         for _, item := range removeP {
    463             tr.Get(item)
    464             i++
    465             if i >= b.N {
    466                 return
    467             }
    468         }
    469     }
    470 }
    471 
    472 func BenchmarkGetCloneEachTime(b *testing.B) {
    473     b.StopTimer()
    474     insertP := perm(benchmarkTreeSize)
    475     removeP := perm(benchmarkTreeSize)
    476     b.StartTimer()
    477     i := 0
    478     for i < b.N {
    479         b.StopTimer()
    480         tr := New(*btreeDegree)
    481         for _, v := range insertP {
    482             tr.ReplaceOrInsert(v)
    483         }
    484         b.StartTimer()
    485         for _, item := range removeP {
    486             tr = tr.Clone()
    487             tr.Get(item)
    488             i++
    489             if i >= b.N {
    490                 return
    491             }
    492         }
    493     }
    494 }
    495 
    496 type byInts []Item
    497 
    498 func (a byInts) Len() int {
    499     return len(a)
    500 }
    501 
    502 func (a byInts) Less(i, j int) bool {
    503     return a[i].(Int) < a[j].(Int)
    504 }
    505 
    506 func (a byInts) Swap(i, j int) {
    507     a[i], a[j] = a[j], a[i]
    508 }
    509 
    510 func BenchmarkAscend(b *testing.B) {
    511     arr := perm(benchmarkTreeSize)
    512     tr := New(*btreeDegree)
    513     for _, v := range arr {
    514         tr.ReplaceOrInsert(v)
    515     }
    516     sort.Sort(byInts(arr))
    517     b.ResetTimer()
    518     for i := 0; i < b.N; i++ {
    519         j := 0
    520         tr.Ascend(func(item Item) bool {
    521             if item.(Int) != arr[j].(Int) {
    522                 b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
    523             }
    524             j++
    525             return true
    526         })
    527     }
    528 }
    529 
    530 func BenchmarkDescend(b *testing.B) {
    531     arr := perm(benchmarkTreeSize)
    532     tr := New(*btreeDegree)
    533     for _, v := range arr {
    534         tr.ReplaceOrInsert(v)
    535     }
    536     sort.Sort(byInts(arr))
    537     b.ResetTimer()
    538     for i := 0; i < b.N; i++ {
    539         j := len(arr) - 1
    540         tr.Descend(func(item Item) bool {
    541             if item.(Int) != arr[j].(Int) {
    542                 b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
    543             }
    544             j--
    545             return true
    546         })
    547     }
    548 }
    549 func BenchmarkAscendRange(b *testing.B) {
    550     arr := perm(benchmarkTreeSize)
    551     tr := New(*btreeDegree)
    552     for _, v := range arr {
    553         tr.ReplaceOrInsert(v)
    554     }
    555     sort.Sort(byInts(arr))
    556     b.ResetTimer()
    557     for i := 0; i < b.N; i++ {
    558         j := 100
    559         tr.AscendRange(Int(100), arr[len(arr)-100], func(item Item) bool {
    560             if item.(Int) != arr[j].(Int) {
    561                 b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
    562             }
    563             j++
    564             return true
    565         })
    566         if j != len(arr)-100 {
    567             b.Fatalf("expected: %v, got %v", len(arr)-100, j)
    568         }
    569     }
    570 }
    571 
    572 func BenchmarkDescendRange(b *testing.B) {
    573     arr := perm(benchmarkTreeSize)
    574     tr := New(*btreeDegree)
    575     for _, v := range arr {
    576         tr.ReplaceOrInsert(v)
    577     }
    578     sort.Sort(byInts(arr))
    579     b.ResetTimer()
    580     for i := 0; i < b.N; i++ {
    581         j := len(arr) - 100
    582         tr.DescendRange(arr[len(arr)-100], Int(100), func(item Item) bool {
    583             if item.(Int) != arr[j].(Int) {
    584                 b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
    585             }
    586             j--
    587             return true
    588         })
    589         if j != 100 {
    590             b.Fatalf("expected: %v, got %v", len(arr)-100, j)
    591         }
    592     }
    593 }
    594 func BenchmarkAscendGreaterOrEqual(b *testing.B) {
    595     arr := perm(benchmarkTreeSize)
    596     tr := New(*btreeDegree)
    597     for _, v := range arr {
    598         tr.ReplaceOrInsert(v)
    599     }
    600     sort.Sort(byInts(arr))
    601     b.ResetTimer()
    602     for i := 0; i < b.N; i++ {
    603         j := 100
    604         k := 0
    605         tr.AscendGreaterOrEqual(Int(100), func(item Item) bool {
    606             if item.(Int) != arr[j].(Int) {
    607                 b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
    608             }
    609             j++
    610             k++
    611             return true
    612         })
    613         if j != len(arr) {
    614             b.Fatalf("expected: %v, got %v", len(arr), j)
    615         }
    616         if k != len(arr)-100 {
    617             b.Fatalf("expected: %v, got %v", len(arr)-100, k)
    618         }
    619     }
    620 }
    621 func BenchmarkDescendLessOrEqual(b *testing.B) {
    622     arr := perm(benchmarkTreeSize)
    623     tr := New(*btreeDegree)
    624     for _, v := range arr {
    625         tr.ReplaceOrInsert(v)
    626     }
    627     sort.Sort(byInts(arr))
    628     b.ResetTimer()
    629     for i := 0; i < b.N; i++ {
    630         j := len(arr) - 100
    631         k := len(arr)
    632         tr.DescendLessOrEqual(arr[len(arr)-100], func(item Item) bool {
    633             if item.(Int) != arr[j].(Int) {
    634                 b.Fatalf("mismatch: expected: %v, got %v", arr[j].(Int), item.(Int))
    635             }
    636             j--
    637             k--
    638             return true
    639         })
    640         if j != -1 {
    641             b.Fatalf("expected: %v, got %v", -1, j)
    642         }
    643         if k != 99 {
    644             b.Fatalf("expected: %v, got %v", 99, k)
    645         }
    646     }
    647 }
    648 
    649 const cloneTestSize = 10000
    650 
    651 func cloneTest(t *testing.T, b *BTree, start int, p []Item, wg *sync.WaitGroup, trees *[]*BTree) {
    652     t.Logf("Starting new clone at %v", start)
    653     *trees = append(*trees, b)
    654     for i := start; i < cloneTestSize; i++ {
    655         b.ReplaceOrInsert(p[i])
    656         if i%(cloneTestSize/5) == 0 {
    657             wg.Add(1)
    658             go cloneTest(t, b.Clone(), i+1, p, wg, trees)
    659         }
    660     }
    661     wg.Done()
    662 }
    663 
    664 func TestCloneConcurrentOperations(t *testing.T) {
    665     b := New(*btreeDegree)
    666     trees := []*BTree{}
    667     p := perm(cloneTestSize)
    668     var wg sync.WaitGroup
    669     wg.Add(1)
    670     go cloneTest(t, b, 0, p, &wg, &trees)
    671     wg.Wait()
    672     want := rang(cloneTestSize)
    673     t.Logf("Starting equality checks on %d trees", len(trees))
    674     for i, tree := range trees {
    675         if !reflect.DeepEqual(want, all(tree)) {
    676             t.Errorf("tree %v mismatch", i)
    677         }
    678     }
    679     t.Log("Removing half from first half")
    680     toRemove := rang(cloneTestSize)[cloneTestSize/2:]
    681     for i := 0; i < len(trees)/2; i++ {
    682         tree := trees[i]
    683         wg.Add(1)
    684         go func() {
    685             for _, item := range toRemove {
    686                 tree.Delete(item)
    687             }
    688             wg.Done()
    689         }()
    690     }
    691     wg.Wait()
    692     t.Log("Checking all values again")
    693     for i, tree := range trees {
    694         var wantpart []Item
    695         if i < len(trees)/2 {
    696             wantpart = want[:cloneTestSize/2]
    697         } else {
    698             wantpart = want
    699         }
    700         if got := all(tree); !reflect.DeepEqual(wantpart, got) {
    701             t.Errorf("tree %v mismatch, want %v got %v", i, len(want), len(got))
    702         }
    703     }
    704 }
    705 
    706 func BenchmarkDeleteAndRestore(b *testing.B) {
    707     items := perm(16392)
    708     b.ResetTimer()
    709     b.Run(`CopyBigFreeList`, func(b *testing.B) {
    710         fl := NewFreeList(16392)
    711         tr := NewWithFreeList(*btreeDegree, fl)
    712         for _, v := range items {
    713             tr.ReplaceOrInsert(v)
    714         }
    715         b.ReportAllocs()
    716         b.ResetTimer()
    717         for i := 0; i < b.N; i++ {
    718             dels := make([]Item, 0, tr.Len())
    719             tr.Ascend(ItemIterator(func(b Item) bool {
    720                 dels = append(dels, b)
    721                 return true
    722             }))
    723             for _, del := range dels {
    724                 tr.Delete(del)
    725             }
    726             // tr is now empty, we make a new empty copy of it.
    727             tr = NewWithFreeList(*btreeDegree, fl)
    728             for _, v := range items {
    729                 tr.ReplaceOrInsert(v)
    730             }
    731         }
    732     })
    733     b.Run(`Copy`, func(b *testing.B) {
    734         tr := New(*btreeDegree)
    735         for _, v := range items {
    736             tr.ReplaceOrInsert(v)
    737         }
    738         b.ReportAllocs()
    739         b.ResetTimer()
    740         for i := 0; i < b.N; i++ {
    741             dels := make([]Item, 0, tr.Len())
    742             tr.Ascend(ItemIterator(func(b Item) bool {
    743                 dels = append(dels, b)
    744                 return true
    745             }))
    746             for _, del := range dels {
    747                 tr.Delete(del)
    748             }
    749             // tr is now empty, we make a new empty copy of it.
    750             tr = New(*btreeDegree)
    751             for _, v := range items {
    752                 tr.ReplaceOrInsert(v)
    753             }
    754         }
    755     })
    756     b.Run(`ClearBigFreelist`, func(b *testing.B) {
    757         fl := NewFreeList(16392)
    758         tr := NewWithFreeList(*btreeDegree, fl)
    759         for _, v := range items {
    760             tr.ReplaceOrInsert(v)
    761         }
    762         b.ReportAllocs()
    763         b.ResetTimer()
    764         for i := 0; i < b.N; i++ {
    765             tr.Clear(true)
    766             for _, v := range items {
    767                 tr.ReplaceOrInsert(v)
    768             }
    769         }
    770     })
    771     b.Run(`Clear`, func(b *testing.B) {
    772         tr := New(*btreeDegree)
    773         for _, v := range items {
    774             tr.ReplaceOrInsert(v)
    775         }
    776         b.ReportAllocs()
    777         b.ResetTimer()
    778         for i := 0; i < b.N; i++ {
    779             tr.Clear(true)
    780             for _, v := range items {
    781                 tr.ReplaceOrInsert(v)
    782             }
    783         }
    784     })
    785 }
    btree_test.go
     1 // Copyright 2014 Google Inc.
     2 //
     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
     6 //
     7 //     http://www.apache.org/licenses/LICENSE-2.0
     8 //
     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.
    14 
    15 // +build ignore
    16 
    17 // This binary compares memory usage between btree and gollrb.
    18 package main
    19 
    20 import (
    21     "flag"
    22     "fmt"
    23     "math/rand"
    24     "runtime"
    25     "time"
    26 
    27     "github.com/google/btree"
    28     "github.com/petar/GoLLRB/llrb"
    29 )
    30 
    31 var (
    32     size   = flag.Int("size", 1000000, "size of the tree to build")
    33     degree = flag.Int("degree", 8, "degree of btree")
    34     gollrb = flag.Bool("llrb", false, "use llrb instead of btree")
    35 )
    36 
    37 func main() {
    38     flag.Parse()
    39     vals := rand.Perm(*size)
    40     var t, v interface{}
    41     v = vals
    42     var stats runtime.MemStats
    43     for i := 0; i < 10; i++ {
    44         runtime.GC()
    45     }
    46     fmt.Println("-------- BEFORE ----------")
    47     runtime.ReadMemStats(&stats)
    48     fmt.Printf("%+v
    ", stats)
    49     start := time.Now()
    50     if *gollrb {
    51         tr := llrb.New()
    52         for _, v := range vals {
    53             tr.ReplaceOrInsert(llrb.Int(v))
    54         }
    55         t = tr // keep it around
    56     } else {
    57         tr := btree.New(*degree)
    58         for _, v := range vals {
    59             tr.ReplaceOrInsert(btree.Int(v))
    60         }
    61         t = tr // keep it around
    62     }
    63     fmt.Printf("%v inserts in %v
    ", *size, time.Since(start))
    64     fmt.Println("-------- AFTER ----------")
    65     runtime.ReadMemStats(&stats)
    66     fmt.Printf("%+v
    ", stats)
    67     for i := 0; i < 10; i++ {
    68         runtime.GC()
    69     }
    70     fmt.Println("-------- AFTER GC ----------")
    71     runtime.ReadMemStats(&stats)
    72     fmt.Printf("%+v
    ", stats)
    73     if t == v {
    74         fmt.Println("to make sure vals and tree aren't GC'd")
    75     }
    76 }
    btree_mem.go
      1 // Copyright 2014 Google Inc.
      2 //
      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
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      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.
     14 
     15 // Package btree implements in-memory B-Trees of arbitrary degree.
     16 //
     17 // btree implements an in-memory B-Tree for use as an ordered data structure.
     18 // It is not meant for persistent storage solutions.
     19 //
     20 // It has a flatter structure than an equivalent red-black or other binary tree,
     21 // which in some cases yields better memory usage and/or performance.
     22 // See some discussion on the matter here:
     23 //   http://google-opensource.blogspot.com/2013/01/c-containers-that-save-memory-and-time.html
     24 // Note, though, that this project is in no way related to the C++ B-Tree
     25 // implementation written about there.
     26 //
     27 // Within this tree, each node contains a slice of items and a (possibly nil)
     28 // slice of children.  For basic numeric values or raw structs, this can cause
     29 // efficiency differences when compared to equivalent C++ template code that
     30 // stores values in arrays within the node:
     31 //   * Due to the overhead of storing values as interfaces (each
     32 //     value needs to be stored as the value itself, then 2 words for the
     33 //     interface pointing to that value and its type), resulting in higher
     34 //     memory use.
     35 //   * Since interfaces can point to values anywhere in memory, values are
     36 //     most likely not stored in contiguous blocks, resulting in a higher
     37 //     number of cache misses.
     38 // These issues don't tend to matter, though, when working with strings or other
     39 // heap-allocated structures, since C++-equivalent structures also must store
     40 // pointers and also distribute their values across the heap.
     41 //
     42 // This implementation is designed to be a drop-in replacement to gollrb.LLRB
     43 // trees, (http://github.com/petar/gollrb), an excellent and probably the most
     44 // widely used ordered tree implementation in the Go ecosystem currently.
     45 // Its functions, therefore, exactly mirror those of
     46 // llrb.LLRB where possible.  Unlike gollrb, though, we currently don't
     47 // support storing multiple equivalent values.
     48 package btree
     49 
     50 import (
     51     "fmt"
     52     "io"
     53     "sort"
     54     "strings"
     55     "sync"
     56 )
     57 
     58 // Item represents a single object in the tree.
     59 type Item interface {
     60     // Less tests whether the current item is less than the given argument.
     61     //
     62     // This must provide a strict weak ordering.
     63     // If !a.Less(b) && !b.Less(a), we treat this to mean a == b (i.e. we can only
     64     // hold one of either a or b in the tree).
     65     Less(than Item) bool
     66 }
     67 
     68 const (
     69     DefaultFreeListSize = 32
     70 )
     71 
     72 var (
     73     nilItems    = make(items, 16)
     74     nilChildren = make(children, 16)
     75 )
     76 
     77 // FreeList represents a free list of btree nodes. By default each
     78 // BTree has its own FreeList, but multiple BTrees can share the same
     79 // FreeList.
     80 // Two Btrees using the same freelist are safe for concurrent write access.
     81 type FreeList struct {
     82     mu       sync.Mutex
     83     freelist []*node
     84 }
     85 
     86 // NewFreeList creates a new free list.
     87 // size is the maximum size of the returned free list.
     88 func NewFreeList(size int) *FreeList {
     89     return &FreeList{freelist: make([]*node, 0, size)}
     90 }
     91 
     92 func (f *FreeList) newNode() (n *node) {
     93     f.mu.Lock()
     94     index := len(f.freelist) - 1
     95     if index < 0 {
     96         f.mu.Unlock()
     97         return new(node)
     98     }
     99     n = f.freelist[index]
    100     f.freelist[index] = nil
    101     f.freelist = f.freelist[:index]
    102     f.mu.Unlock()
    103     return
    104 }
    105 
    106 // freeNode adds the given node to the list, returning true if it was added
    107 // and false if it was discarded.
    108 func (f *FreeList) freeNode(n *node) (out bool) {
    109     f.mu.Lock()
    110     if len(f.freelist) < cap(f.freelist) {
    111         f.freelist = append(f.freelist, n)
    112         out = true
    113     }
    114     f.mu.Unlock()
    115     return
    116 }
    117 
    118 // ItemIterator allows callers of Ascend* to iterate in-order over portions of
    119 // the tree.  When this function returns false, iteration will stop and the
    120 // associated Ascend* function will immediately return.
    121 type ItemIterator func(i Item) bool
    122 
    123 // New creates a new B-Tree with the given degree.
    124 //
    125 // New(2), for example, will create a 2-3-4 tree (each node contains 1-3 items
    126 // and 2-4 children).
    127 func New(degree int) *BTree {
    128     return NewWithFreeList(degree, NewFreeList(DefaultFreeListSize))
    129 }
    130 
    131 // NewWithFreeList creates a new B-Tree that uses the given node free list.
    132 func NewWithFreeList(degree int, f *FreeList) *BTree {
    133     if degree <= 1 {
    134         panic("bad degree")
    135     }
    136     return &BTree{
    137         degree: degree,
    138         cow:    &copyOnWriteContext{freelist: f},
    139     }
    140 }
    141 
    142 // items stores items in a node.
    143 type items []Item
    144 
    145 // insertAt inserts a value into the given index, pushing all subsequent values
    146 // forward.
    147 func (s *items) insertAt(index int, item Item) {
    148     *s = append(*s, nil)
    149     if index < len(*s) {
    150         copy((*s)[index+1:], (*s)[index:])
    151     }
    152     (*s)[index] = item
    153 }
    154 
    155 // removeAt removes a value at a given index, pulling all subsequent values
    156 // back.
    157 func (s *items) removeAt(index int) Item {
    158     item := (*s)[index]
    159     copy((*s)[index:], (*s)[index+1:])
    160     (*s)[len(*s)-1] = nil
    161     *s = (*s)[:len(*s)-1]
    162     return item
    163 }
    164 
    165 // pop removes and returns the last element in the list.
    166 func (s *items) pop() (out Item) {
    167     index := len(*s) - 1
    168     out = (*s)[index]
    169     (*s)[index] = nil
    170     *s = (*s)[:index]
    171     return
    172 }
    173 
    174 // truncate truncates this instance at index so that it contains only the
    175 // first index items. index must be less than or equal to length.
    176 func (s *items) truncate(index int) {
    177     var toClear items
    178     *s, toClear = (*s)[:index], (*s)[index:]
    179     for len(toClear) > 0 {
    180         toClear = toClear[copy(toClear, nilItems):]
    181     }
    182 }
    183 
    184 // find returns the index where the given item should be inserted into this
    185 // list.  'found' is true if the item already exists in the list at the given
    186 // index.
    187 func (s items) find(item Item) (index int, found bool) {
    188     i := sort.Search(len(s), func(i int) bool {
    189         return item.Less(s[i])
    190     })
    191     if i > 0 && !s[i-1].Less(item) {
    192         return i - 1, true
    193     }
    194     return i, false
    195 }
    196 
    197 // children stores child nodes in a node.
    198 type children []*node
    199 
    200 // insertAt inserts a value into the given index, pushing all subsequent values
    201 // forward.
    202 func (s *children) insertAt(index int, n *node) {
    203     *s = append(*s, nil)
    204     if index < len(*s) {
    205         copy((*s)[index+1:], (*s)[index:])
    206     }
    207     (*s)[index] = n
    208 }
    209 
    210 // removeAt removes a value at a given index, pulling all subsequent values
    211 // back.
    212 func (s *children) removeAt(index int) *node {
    213     n := (*s)[index]
    214     copy((*s)[index:], (*s)[index+1:])
    215     (*s)[len(*s)-1] = nil
    216     *s = (*s)[:len(*s)-1]
    217     return n
    218 }
    219 
    220 // pop removes and returns the last element in the list.
    221 func (s *children) pop() (out *node) {
    222     index := len(*s) - 1
    223     out = (*s)[index]
    224     (*s)[index] = nil
    225     *s = (*s)[:index]
    226     return
    227 }
    228 
    229 // truncate truncates this instance at index so that it contains only the
    230 // first index children. index must be less than or equal to length.
    231 func (s *children) truncate(index int) {
    232     var toClear children
    233     *s, toClear = (*s)[:index], (*s)[index:]
    234     for len(toClear) > 0 {
    235         toClear = toClear[copy(toClear, nilChildren):]
    236     }
    237 }
    238 
    239 // node is an internal node in a tree.
    240 //
    241 // It must at all times maintain the invariant that either
    242 //   * len(children) == 0, len(items) unconstrained
    243 //   * len(children) == len(items) + 1
    244 type node struct {
    245     items    items
    246     children children
    247     cow      *copyOnWriteContext
    248 }
    249 
    250 func (n *node) mutableFor(cow *copyOnWriteContext) *node {
    251     if n.cow == cow {
    252         return n
    253     }
    254     out := cow.newNode()
    255     if cap(out.items) >= len(n.items) {
    256         out.items = out.items[:len(n.items)]
    257     } else {
    258         out.items = make(items, len(n.items), cap(n.items))
    259     }
    260     copy(out.items, n.items)
    261     // Copy children
    262     if cap(out.children) >= len(n.children) {
    263         out.children = out.children[:len(n.children)]
    264     } else {
    265         out.children = make(children, len(n.children), cap(n.children))
    266     }
    267     copy(out.children, n.children)
    268     return out
    269 }
    270 
    271 func (n *node) mutableChild(i int) *node {
    272     c := n.children[i].mutableFor(n.cow)
    273     n.children[i] = c
    274     return c
    275 }
    276 
    277 // split splits the given node at the given index.  The current node shrinks,
    278 // and this function returns the item that existed at that index and a new node
    279 // containing all items/children after it.
    280 func (n *node) split(i int) (Item, *node) {
    281     item := n.items[i]
    282     next := n.cow.newNode()
    283     next.items = append(next.items, n.items[i+1:]...)
    284     n.items.truncate(i)
    285     if len(n.children) > 0 {
    286         next.children = append(next.children, n.children[i+1:]...)
    287         n.children.truncate(i + 1)
    288     }
    289     return item, next
    290 }
    291 
    292 // maybeSplitChild checks if a child should be split, and if so splits it.
    293 // Returns whether or not a split occurred.
    294 func (n *node) maybeSplitChild(i, maxItems int) bool {
    295     if len(n.children[i].items) < maxItems {
    296         return false
    297     }
    298     first := n.mutableChild(i)
    299     item, second := first.split(maxItems / 2)
    300     n.items.insertAt(i, item)
    301     n.children.insertAt(i+1, second)
    302     return true
    303 }
    304 
    305 // insert inserts an item into the subtree rooted at this node, making sure
    306 // no nodes in the subtree exceed maxItems items.  Should an equivalent item be
    307 // be found/replaced by insert, it will be returned.
    308 func (n *node) insert(item Item, maxItems int) Item {
    309     i, found := n.items.find(item)
    310     if found {
    311         out := n.items[i]
    312         n.items[i] = item
    313         return out
    314     }
    315     if len(n.children) == 0 {
    316         n.items.insertAt(i, item)
    317         return nil
    318     }
    319     if n.maybeSplitChild(i, maxItems) {
    320         inTree := n.items[i]
    321         switch {
    322         case item.Less(inTree):
    323             // no change, we want first split node
    324         case inTree.Less(item):
    325             i++ // we want second split node
    326         default:
    327             out := n.items[i]
    328             n.items[i] = item
    329             return out
    330         }
    331     }
    332     return n.mutableChild(i).insert(item, maxItems)
    333 }
    334 
    335 // get finds the given key in the subtree and returns it.
    336 func (n *node) get(key Item) Item {
    337     i, found := n.items.find(key)
    338     if found {
    339         return n.items[i]
    340     } else if len(n.children) > 0 {
    341         return n.children[i].get(key)
    342     }
    343     return nil
    344 }
    345 
    346 // min returns the first item in the subtree.
    347 func min(n *node) Item {
    348     if n == nil {
    349         return nil
    350     }
    351     for len(n.children) > 0 {
    352         n = n.children[0]
    353     }
    354     if len(n.items) == 0 {
    355         return nil
    356     }
    357     return n.items[0]
    358 }
    359 
    360 // max returns the last item in the subtree.
    361 func max(n *node) Item {
    362     if n == nil {
    363         return nil
    364     }
    365     for len(n.children) > 0 {
    366         n = n.children[len(n.children)-1]
    367     }
    368     if len(n.items) == 0 {
    369         return nil
    370     }
    371     return n.items[len(n.items)-1]
    372 }
    373 
    374 // toRemove details what item to remove in a node.remove call.
    375 type toRemove int
    376 
    377 const (
    378     removeItem toRemove = iota // removes the given item
    379     removeMin                  // removes smallest item in the subtree
    380     removeMax                  // removes largest item in the subtree
    381 )
    382 
    383 // remove removes an item from the subtree rooted at this node.
    384 func (n *node) remove(item Item, minItems int, typ toRemove) Item {
    385     var i int
    386     var found bool
    387     switch typ {
    388     case removeMax:
    389         if len(n.children) == 0 {
    390             return n.items.pop()
    391         }
    392         i = len(n.items)
    393     case removeMin:
    394         if len(n.children) == 0 {
    395             return n.items.removeAt(0)
    396         }
    397         i = 0
    398     case removeItem:
    399         i, found = n.items.find(item)
    400         if len(n.children) == 0 {
    401             if found {
    402                 return n.items.removeAt(i)
    403             }
    404             return nil
    405         }
    406     default:
    407         panic("invalid type")
    408     }
    409     // If we get to here, we have children.
    410     if len(n.children[i].items) <= minItems {
    411         return n.growChildAndRemove(i, item, minItems, typ)
    412     }
    413     child := n.mutableChild(i)
    414     // Either we had enough items to begin with, or we've done some
    415     // merging/stealing, because we've got enough now and we're ready to return
    416     // stuff.
    417     if found {
    418         // The item exists at index 'i', and the child we've selected can give us a
    419         // predecessor, since if we've gotten here it's got > minItems items in it.
    420         out := n.items[i]
    421         // We use our special-case 'remove' call with typ=maxItem to pull the
    422         // predecessor of item i (the rightmost leaf of our immediate left child)
    423         // and set it into where we pulled the item from.
    424         n.items[i] = child.remove(nil, minItems, removeMax)
    425         return out
    426     }
    427     // Final recursive call.  Once we're here, we know that the item isn't in this
    428     // node and that the child is big enough to remove from.
    429     return child.remove(item, minItems, typ)
    430 }
    431 
    432 // growChildAndRemove grows child 'i' to make sure it's possible to remove an
    433 // item from it while keeping it at minItems, then calls remove to actually
    434 // remove it.
    435 //
    436 // Most documentation says we have to do two sets of special casing:
    437 //   1) item is in this node
    438 //   2) item is in child
    439 // In both cases, we need to handle the two subcases:
    440 //   A) node has enough values that it can spare one
    441 //   B) node doesn't have enough values
    442 // For the latter, we have to check:
    443 //   a) left sibling has node to spare
    444 //   b) right sibling has node to spare
    445 //   c) we must merge
    446 // To simplify our code here, we handle cases #1 and #2 the same:
    447 // If a node doesn't have enough items, we make sure it does (using a,b,c).
    448 // We then simply redo our remove call, and the second time (regardless of
    449 // whether we're in case 1 or 2), we'll have enough items and can guarantee
    450 // that we hit case A.
    451 func (n *node) growChildAndRemove(i int, item Item, minItems int, typ toRemove) Item {
    452     if i > 0 && len(n.children[i-1].items) > minItems {
    453         // Steal from left child
    454         child := n.mutableChild(i)
    455         stealFrom := n.mutableChild(i - 1)
    456         stolenItem := stealFrom.items.pop()
    457         child.items.insertAt(0, n.items[i-1])
    458         n.items[i-1] = stolenItem
    459         if len(stealFrom.children) > 0 {
    460             child.children.insertAt(0, stealFrom.children.pop())
    461         }
    462     } else if i < len(n.items) && len(n.children[i+1].items) > minItems {
    463         // steal from right child
    464         child := n.mutableChild(i)
    465         stealFrom := n.mutableChild(i + 1)
    466         stolenItem := stealFrom.items.removeAt(0)
    467         child.items = append(child.items, n.items[i])
    468         n.items[i] = stolenItem
    469         if len(stealFrom.children) > 0 {
    470             child.children = append(child.children, stealFrom.children.removeAt(0))
    471         }
    472     } else {
    473         if i >= len(n.items) {
    474             i--
    475         }
    476         child := n.mutableChild(i)
    477         // merge with right child
    478         mergeItem := n.items.removeAt(i)
    479         mergeChild := n.children.removeAt(i + 1)
    480         child.items = append(child.items, mergeItem)
    481         child.items = append(child.items, mergeChild.items...)
    482         child.children = append(child.children, mergeChild.children...)
    483         n.cow.freeNode(mergeChild)
    484     }
    485     return n.remove(item, minItems, typ)
    486 }
    487 
    488 type direction int
    489 
    490 const (
    491     descend = direction(-1)
    492     ascend  = direction(+1)
    493 )
    494 
    495 // iterate provides a simple method for iterating over elements in the tree.
    496 //
    497 // When ascending, the 'start' should be less than 'stop' and when descending,
    498 // the 'start' should be greater than 'stop'. Setting 'includeStart' to true
    499 // will force the iterator to include the first item when it equals 'start',
    500 // thus creating a "greaterOrEqual" or "lessThanEqual" rather than just a
    501 // "greaterThan" or "lessThan" queries.
    502 func (n *node) iterate(dir direction, start, stop Item, includeStart bool, hit bool, iter ItemIterator) (bool, bool) {
    503     var ok, found bool
    504     var index int
    505     switch dir {
    506     case ascend:
    507         if start != nil {
    508             index, _ = n.items.find(start)
    509         }
    510         for i := index; i < len(n.items); i++ {
    511             if len(n.children) > 0 {
    512                 if hit, ok = n.children[i].iterate(dir, start, stop, includeStart, hit, iter); !ok {
    513                     return hit, false
    514                 }
    515             }
    516             if !includeStart && !hit && start != nil && !start.Less(n.items[i]) {
    517                 hit = true
    518                 continue
    519             }
    520             hit = true
    521             if stop != nil && !n.items[i].Less(stop) {
    522                 return hit, false
    523             }
    524             if !iter(n.items[i]) {
    525                 return hit, false
    526             }
    527         }
    528         if len(n.children) > 0 {
    529             if hit, ok = n.children[len(n.children)-1].iterate(dir, start, stop, includeStart, hit, iter); !ok {
    530                 return hit, false
    531             }
    532         }
    533     case descend:
    534         if start != nil {
    535             index, found = n.items.find(start)
    536             if !found {
    537                 index = index - 1
    538             }
    539         } else {
    540             index = len(n.items) - 1
    541         }
    542         for i := index; i >= 0; i-- {
    543             if start != nil && !n.items[i].Less(start) {
    544                 if !includeStart || hit || start.Less(n.items[i]) {
    545                     continue
    546                 }
    547             }
    548             if len(n.children) > 0 {
    549                 if hit, ok = n.children[i+1].iterate(dir, start, stop, includeStart, hit, iter); !ok {
    550                     return hit, false
    551                 }
    552             }
    553             if stop != nil && !stop.Less(n.items[i]) {
    554                 return hit, false //    continue
    555             }
    556             hit = true
    557             if !iter(n.items[i]) {
    558                 return hit, false
    559             }
    560         }
    561         if len(n.children) > 0 {
    562             if hit, ok = n.children[0].iterate(dir, start, stop, includeStart, hit, iter); !ok {
    563                 return hit, false
    564             }
    565         }
    566     }
    567     return hit, true
    568 }
    569 
    570 // Used for testing/debugging purposes.
    571 func (n *node) print(w io.Writer, level int) {
    572     fmt.Fprintf(w, "%sNODE:%v
    ", strings.Repeat("  ", level), n.items)
    573     for _, c := range n.children {
    574         c.print(w, level+1)
    575     }
    576 }
    577 
    578 // BTree is an implementation of a B-Tree.
    579 //
    580 // BTree stores Item instances in an ordered structure, allowing easy insertion,
    581 // removal, and iteration.
    582 //
    583 // Write operations are not safe for concurrent mutation by multiple
    584 // goroutines, but Read operations are.
    585 type BTree struct {
    586     degree int
    587     length int
    588     root   *node
    589     cow    *copyOnWriteContext
    590 }
    591 
    592 // copyOnWriteContext pointers determine node ownership... a tree with a write
    593 // context equivalent to a node's write context is allowed to modify that node.
    594 // A tree whose write context does not match a node's is not allowed to modify
    595 // it, and must create a new, writable copy (IE: it's a Clone).
    596 //
    597 // When doing any write operation, we maintain the invariant that the current
    598 // node's context is equal to the context of the tree that requested the write.
    599 // We do this by, before we descend into any node, creating a copy with the
    600 // correct context if the contexts don't match.
    601 //
    602 // Since the node we're currently visiting on any write has the requesting
    603 // tree's context, that node is modifiable in place.  Children of that node may
    604 // not share context, but before we descend into them, we'll make a mutable
    605 // copy.
    606 type copyOnWriteContext struct {
    607     freelist *FreeList
    608 }
    609 
    610 // Clone clones the btree, lazily.  Clone should not be called concurrently,
    611 // but the original tree (t) and the new tree (t2) can be used concurrently
    612 // once the Clone call completes.
    613 //
    614 // The internal tree structure of b is marked read-only and shared between t and
    615 // t2.  Writes to both t and t2 use copy-on-write logic, creating new nodes
    616 // whenever one of b's original nodes would have been modified.  Read operations
    617 // should have no performance degredation.  Write operations for both t and t2
    618 // will initially experience minor slow-downs caused by additional allocs and
    619 // copies due to the aforementioned copy-on-write logic, but should converge to
    620 // the original performance characteristics of the original tree.
    621 func (t *BTree) Clone() (t2 *BTree) {
    622     // Create two entirely new copy-on-write contexts.
    623     // This operation effectively creates three trees:
    624     //   the original, shared nodes (old b.cow)
    625     //   the new b.cow nodes
    626     //   the new out.cow nodes
    627     cow1, cow2 := *t.cow, *t.cow
    628     out := *t
    629     t.cow = &cow1
    630     out.cow = &cow2
    631     return &out
    632 }
    633 
    634 // maxItems returns the max number of items to allow per node.
    635 func (t *BTree) maxItems() int {
    636     return t.degree*2 - 1
    637 }
    638 
    639 // minItems returns the min number of items to allow per node (ignored for the
    640 // root node).
    641 func (t *BTree) minItems() int {
    642     return t.degree - 1
    643 }
    644 
    645 func (c *copyOnWriteContext) newNode() (n *node) {
    646     n = c.freelist.newNode()
    647     n.cow = c
    648     return
    649 }
    650 
    651 type freeType int
    652 
    653 const (
    654     ftFreelistFull freeType = iota // node was freed (available for GC, not stored in freelist)
    655     ftStored                       // node was stored in the freelist for later use
    656     ftNotOwned                     // node was ignored by COW, since it's owned by another one
    657 )
    658 
    659 // freeNode frees a node within a given COW context, if it's owned by that
    660 // context.  It returns what happened to the node (see freeType const
    661 // documentation).
    662 func (c *copyOnWriteContext) freeNode(n *node) freeType {
    663     if n.cow == c {
    664         // clear to allow GC
    665         n.items.truncate(0)
    666         n.children.truncate(0)
    667         n.cow = nil
    668         if c.freelist.freeNode(n) {
    669             return ftStored
    670         } else {
    671             return ftFreelistFull
    672         }
    673     } else {
    674         return ftNotOwned
    675     }
    676 }
    677 
    678 // ReplaceOrInsert adds the given item to the tree.  If an item in the tree
    679 // already equals the given one, it is removed from the tree and returned.
    680 // Otherwise, nil is returned.
    681 //
    682 // nil cannot be added to the tree (will panic).
    683 func (t *BTree) ReplaceOrInsert(item Item) Item {
    684     if item == nil {
    685         panic("nil item being added to BTree")
    686     }
    687     if t.root == nil {
    688         t.root = t.cow.newNode()
    689         t.root.items = append(t.root.items, item)
    690         t.length++
    691         return nil
    692     } else {
    693         t.root = t.root.mutableFor(t.cow)
    694         if len(t.root.items) >= t.maxItems() {
    695             item2, second := t.root.split(t.maxItems() / 2)
    696             oldroot := t.root
    697             t.root = t.cow.newNode()
    698             t.root.items = append(t.root.items, item2)
    699             t.root.children = append(t.root.children, oldroot, second)
    700         }
    701     }
    702     out := t.root.insert(item, t.maxItems())
    703     if out == nil {
    704         t.length++
    705     }
    706     return out
    707 }
    708 
    709 // Delete removes an item equal to the passed in item from the tree, returning
    710 // it.  If no such item exists, returns nil.
    711 func (t *BTree) Delete(item Item) Item {
    712     return t.deleteItem(item, removeItem)
    713 }
    714 
    715 // DeleteMin removes the smallest item in the tree and returns it.
    716 // If no such item exists, returns nil.
    717 func (t *BTree) DeleteMin() Item {
    718     return t.deleteItem(nil, removeMin)
    719 }
    720 
    721 // DeleteMax removes the largest item in the tree and returns it.
    722 // If no such item exists, returns nil.
    723 func (t *BTree) DeleteMax() Item {
    724     return t.deleteItem(nil, removeMax)
    725 }
    726 
    727 func (t *BTree) deleteItem(item Item, typ toRemove) Item {
    728     if t.root == nil || len(t.root.items) == 0 {
    729         return nil
    730     }
    731     t.root = t.root.mutableFor(t.cow)
    732     out := t.root.remove(item, t.minItems(), typ)
    733     if len(t.root.items) == 0 && len(t.root.children) > 0 {
    734         oldroot := t.root
    735         t.root = t.root.children[0]
    736         t.cow.freeNode(oldroot)
    737     }
    738     if out != nil {
    739         t.length--
    740     }
    741     return out
    742 }
    743 
    744 // AscendRange calls the iterator for every value in the tree within the range
    745 // [greaterOrEqual, lessThan), until iterator returns false.
    746 func (t *BTree) AscendRange(greaterOrEqual, lessThan Item, iterator ItemIterator) {
    747     if t.root == nil {
    748         return
    749     }
    750     t.root.iterate(ascend, greaterOrEqual, lessThan, true, false, iterator)
    751 }
    752 
    753 // AscendLessThan calls the iterator for every value in the tree within the range
    754 // [first, pivot), until iterator returns false.
    755 func (t *BTree) AscendLessThan(pivot Item, iterator ItemIterator) {
    756     if t.root == nil {
    757         return
    758     }
    759     t.root.iterate(ascend, nil, pivot, false, false, iterator)
    760 }
    761 
    762 // AscendGreaterOrEqual calls the iterator for every value in the tree within
    763 // the range [pivot, last], until iterator returns false.
    764 func (t *BTree) AscendGreaterOrEqual(pivot Item, iterator ItemIterator) {
    765     if t.root == nil {
    766         return
    767     }
    768     t.root.iterate(ascend, pivot, nil, true, false, iterator)
    769 }
    770 
    771 // Ascend calls the iterator for every value in the tree within the range
    772 // [first, last], until iterator returns false.
    773 func (t *BTree) Ascend(iterator ItemIterator) {
    774     if t.root == nil {
    775         return
    776     }
    777     t.root.iterate(ascend, nil, nil, false, false, iterator)
    778 }
    779 
    780 // DescendRange calls the iterator for every value in the tree within the range
    781 // [lessOrEqual, greaterThan), until iterator returns false.
    782 func (t *BTree) DescendRange(lessOrEqual, greaterThan Item, iterator ItemIterator) {
    783     if t.root == nil {
    784         return
    785     }
    786     t.root.iterate(descend, lessOrEqual, greaterThan, true, false, iterator)
    787 }
    788 
    789 // DescendLessOrEqual calls the iterator for every value in the tree within the range
    790 // [pivot, first], until iterator returns false.
    791 func (t *BTree) DescendLessOrEqual(pivot Item, iterator ItemIterator) {
    792     if t.root == nil {
    793         return
    794     }
    795     t.root.iterate(descend, pivot, nil, true, false, iterator)
    796 }
    797 
    798 // DescendGreaterThan calls the iterator for every value in the tree within
    799 // the range (pivot, last], until iterator returns false.
    800 func (t *BTree) DescendGreaterThan(pivot Item, iterator ItemIterator) {
    801     if t.root == nil {
    802         return
    803     }
    804     t.root.iterate(descend, nil, pivot, false, false, iterator)
    805 }
    806 
    807 // Descend calls the iterator for every value in the tree within the range
    808 // [last, first], until iterator returns false.
    809 func (t *BTree) Descend(iterator ItemIterator) {
    810     if t.root == nil {
    811         return
    812     }
    813     t.root.iterate(descend, nil, nil, false, false, iterator)
    814 }
    815 
    816 // Get looks for the key item in the tree, returning it.  It returns nil if
    817 // unable to find that item.
    818 func (t *BTree) Get(key Item) Item {
    819     if t.root == nil {
    820         return nil
    821     }
    822     return t.root.get(key)
    823 }
    824 
    825 // Min returns the smallest item in the tree, or nil if the tree is empty.
    826 func (t *BTree) Min() Item {
    827     return min(t.root)
    828 }
    829 
    830 // Max returns the largest item in the tree, or nil if the tree is empty.
    831 func (t *BTree) Max() Item {
    832     return max(t.root)
    833 }
    834 
    835 // Has returns true if the given key is in the tree.
    836 func (t *BTree) Has(key Item) bool {
    837     return t.Get(key) != nil
    838 }
    839 
    840 // Len returns the number of items currently in the tree.
    841 func (t *BTree) Len() int {
    842     return t.length
    843 }
    844 
    845 // Clear removes all items from the btree.  If addNodesToFreelist is true,
    846 // t's nodes are added to its freelist as part of this call, until the freelist
    847 // is full.  Otherwise, the root node is simply dereferenced and the subtree
    848 // left to Go's normal GC processes.
    849 //
    850 // This can be much faster
    851 // than calling Delete on all elements, because that requires finding/removing
    852 // each element in the tree and updating the tree accordingly.  It also is
    853 // somewhat faster than creating a new tree to replace the old one, because
    854 // nodes from the old tree are reclaimed into the freelist for use by the new
    855 // one, instead of being lost to the garbage collector.
    856 //
    857 // This call takes:
    858 //   O(1): when addNodesToFreelist is false, this is a single operation.
    859 //   O(1): when the freelist is already full, it breaks out immediately
    860 //   O(freelist size):  when the freelist is empty and the nodes are all owned
    861 //       by this tree, nodes are added to the freelist until full.
    862 //   O(tree size):  when all nodes are owned by another tree, all nodes are
    863 //       iterated over looking for nodes to add to the freelist, and due to
    864 //       ownership, none are.
    865 func (t *BTree) Clear(addNodesToFreelist bool) {
    866     if t.root != nil && addNodesToFreelist {
    867         t.root.reset(t.cow)
    868     }
    869     t.root, t.length = nil, 0
    870 }
    871 
    872 // reset returns a subtree to the freelist.  It breaks out immediately if the
    873 // freelist is full, since the only benefit of iterating is to fill that
    874 // freelist up.  Returns true if parent reset call should continue.
    875 func (n *node) reset(c *copyOnWriteContext) bool {
    876     for _, child := range n.children {
    877         if !child.reset(c) {
    878             return false
    879         }
    880     }
    881     return c.freeNode(n) != ftFreelistFull
    882 }
    883 
    884 // Int implements the Item interface for integers.
    885 type Int int
    886 
    887 // Less returns true if int(a) < int(b).
    888 func (a Int) Less(b Item) bool {
    889     return a < b.(Int)
    890 }
    btree.go
    作 者: itdef
    欢迎转帖 请保持文本完整并注明出处
    技术博客 http://www.cnblogs.com/itdef/
    B站算法视频题解
    https://space.bilibili.com/18508846
    qq 151435887
    gitee https://gitee.com/def/
    欢迎c c++ 算法爱好者 windows驱动爱好者 服务器程序员沟通交流
    如果觉得不错,欢迎点赞,你的鼓励就是我的动力
    阿里打赏 微信打赏
  • 相关阅读:
    测试rar/bz2/tar.gz/gz压缩文档完整性
    php中ajax调用出错的问题
    WIN32_LEAN_AND_MEAN宏
    Windows XP SP3下编译安装check-0.10.0
    Windows XP SP3下成功编译CUint2.1-3
    WebService客户端调用的几种方式
    Webservice 返回数据集 DataSet 及Android显示数据集LiveBindings
    REST 服务器调试 RESTDebugger.exe 和浏览器测试 webservice 调试工具
    delphi android路径 TPath 文件路径,文件管理 file path
    RESTClient 控件 从服务器获得数据集 REST
  • 原文地址:https://www.cnblogs.com/itdef/p/9641058.html
Copyright © 2020-2023  润新知