|
package tree_test |
|
|
|
import ( |
|
"fmt" |
|
"math/rand" |
|
"testing" |
|
|
|
"github.com/RoaringBitmap/roaring" |
|
"github.com/biogo/store/interval" |
|
"github.com/toberndo/go-stree/stree" |
|
) |
|
|
|
// Integer-specific intervals |
|
type Interval struct { |
|
Start, End int |
|
UID uintptr |
|
} |
|
|
|
func (i Interval) Overlap(b interval.IntRange) bool { |
|
// Half-open interval indexing. |
|
return i.End > b.Start && i.Start < b.End |
|
} |
|
func (i Interval) ID() uintptr { return i.UID } |
|
func (i Interval) Range() interval.IntRange { return interval.IntRange{i.Start, i.End} } |
|
func (i Interval) String() string { return fmt.Sprintf("[%d,%d)#%d", i.Start, i.End, i.UID) } |
|
|
|
var n_intervals = 30000 |
|
var i_length = 1000 |
|
var chrom_length = 500000000 |
|
var missed = 3 |
|
|
|
func genIntervals(length int, n int, imax int) []Interval { |
|
ivs := make([]Interval, n) |
|
for i := 0; i < n; i++ { |
|
s := rand.Intn(imax) |
|
e := s + length |
|
ivs[i] = Interval{Start: s, End: e} |
|
} |
|
return ivs |
|
} |
|
|
|
func BenchmarkBuildSTree(b *testing.B) { |
|
ivs := genIntervals(i_length, n_intervals, chrom_length) |
|
b.ResetTimer() |
|
for i := 0; i < b.N; i++ { |
|
t := stree.NewTree() |
|
for _, iv := range ivs { |
|
t.Push(iv.Start, iv.End) |
|
} |
|
t.BuildTree() |
|
} |
|
} |
|
|
|
func BenchmarkBuildRBTree(b *testing.B) { |
|
ivs := genIntervals(i_length, n_intervals, chrom_length) |
|
b.ResetTimer() |
|
for i := 0; i < b.N; i++ { |
|
tree := &interval.IntTree{} |
|
for i, iv := range ivs { |
|
iv.UID = uintptr(i) |
|
tree.Insert(iv, false) |
|
} |
|
} |
|
} |
|
|
|
func BenchmarkBuildRoaring(b *testing.B) { |
|
ivs := genIntervals(i_length, n_intervals, chrom_length) |
|
b.ResetTimer() |
|
for i := 0; i < b.N; i++ { |
|
tree := roaring.New() |
|
for i, iv := range ivs { |
|
iv.UID = uintptr(i) |
|
tree.AddRange(uint64(iv.Start), uint64(iv.End)) |
|
} |
|
} |
|
} |
|
|
|
func BenchmarkQuerySRTree(b *testing.B) { |
|
tree := stree.NewTree() |
|
ivs := genIntervals(i_length, n_intervals, chrom_length) |
|
for _, iv := range ivs { |
|
tree.Push(iv.Start, iv.End) |
|
} |
|
tree.BuildTree() |
|
b.ResetTimer() |
|
for i := 0; i < b.N; i++ { |
|
for _, iv := range ivs { |
|
if len(tree.Query(iv.Start, iv.End)) == 0 { |
|
b.Fatalf("expected result for %d-%d", iv.Start, iv.End) |
|
} |
|
for k := 0; k < missed; k++ { |
|
tree.Query(iv.End+3, iv.End+3+i_length) |
|
} |
|
} |
|
} |
|
} |
|
|
|
func BenchmarkQueryRBTree(b *testing.B) { |
|
tree := &interval.IntTree{} |
|
ivs := genIntervals(i_length, n_intervals, chrom_length) |
|
for i, iv := range ivs { |
|
iv.UID = uintptr(i) |
|
tree.Insert(iv, false) |
|
} |
|
b.ResetTimer() |
|
for i := 0; i < b.N; i++ { |
|
for _, iv := range ivs { |
|
if len(tree.Get(Interval{Start: iv.Start, End: iv.End})) == 0 { |
|
b.Fatalf("expected result for %d-%d", iv.Start, iv.End) |
|
} |
|
for k := 0; k < missed; k++ { |
|
tree.Get(&Interval{Start: iv.End + 3, End: iv.End + 3 + i_length}) |
|
} |
|
} |
|
} |
|
} |
|
|
|
func BenchmarkQueryRoaring(b *testing.B) { |
|
tree := roaring.New() |
|
ivs := genIntervals(i_length, n_intervals, chrom_length) |
|
for _, iv := range ivs { |
|
tree.AddRange(uint64(iv.Start), uint64(iv.End)) |
|
} |
|
tree.RunOptimize() |
|
//fmt.Printf("%+v\n", tree.Stats()) |
|
b.ResetTimer() |
|
for i := 0; i < b.N; i++ { |
|
for _, iv := range ivs { |
|
found := false |
|
for p := iv.Start; p < iv.End; p++ { |
|
if tree.Contains(uint32(p)) { |
|
found = true |
|
break |
|
} |
|
|
|
} |
|
if !found { |
|
b.Fatalf("expected result for %d-%d", iv.Start, iv.End) |
|
} |
|
for k := 0; k < missed; k++ { |
|
o := roaring.New() |
|
o.AddRange(uint64(iv.End+3), uint64(iv.End+3+i_length)) |
|
o.Intersects(tree) |
|
/* |
|
for p := iv.End + 3; p < iv.End+3+i_length; p++ { |
|
if tree.Contains(uint32(p)) { |
|
break |
|
} |
|
} |
|
*/ |
|
} |
|
} |
|
} |
|
} |