From 155472b3db9fe2318a17603a7555e35e2dd09196 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Mon, 18 Dec 2017 14:01:11 -0600 Subject: [PATCH 1/8] added benchmark for various container usage patterns --- roaring/roaring_test.go | 140 +++++++++++++++++++++++++++++++++------- 1 file changed, 115 insertions(+), 25 deletions(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index f6ac33036..2a86c770a 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1062,31 +1062,6 @@ var benchmarkBitmapIntersectionCountData struct { a, b *roaring.Bitmap } -func BenchmarkBitmap_IntersectionCount_ArrayBitmap(b *testing.B) { - data := &benchmarkBitmapIntersectionCountData - if data.a == nil { - const max = (1 << 24) / 64 - - // Build bitmap with array container. - data.a = roaring.NewBitmap() - for i, n := 0, rand.Intn(roaring.ArrayMaxSize); i < n; i++ { - data.a.Add(uint64(rand.Intn(max))) - } - - // Build bitmap with bitmap container. - data.b = roaring.NewBitmap() - for i, n := 0, roaring.ArrayMaxSize*2; i < n; i++ { - data.b.Add(uint64(i * 3)) - } - } - - // Reset timer & benchmark. - b.ResetTimer() - for i := 0; i < b.N; i++ { - data.a.IntersectionCount(data.b) - } -} - // GenerateUint64Slice generates between [0, n) random uint64 numbers between min and max. func GenerateUint64Slice(n int, min, max uint64, sorted bool, rand *rand.Rand) []uint64 { a := make([]uint64, rand.Intn(n)) @@ -1137,3 +1112,118 @@ func TestBitmap_Intersect(t *testing.T) { t.Fatalf("Counts do not match %d %d", bm0.Count(), result.Count()) } } + +func BenchmarkBitmap_IntersectionCount_ArrayBitmap(b *testing.B) { + data := &benchmarkBitmapIntersectionCountData + if data.a == nil { + const max = (1 << 24) / 64 + + // Build bitmap with array container. + data.a = roaring.NewBitmap() + for i, n := 0, rand.Intn(roaring.ArrayMaxSize); i < n; i++ { + data.a.Add(uint64(rand.Intn(max))) + } + + // Build bitmap with bitmap container. + data.b = roaring.NewBitmap() + for i, n := 0, roaring.ArrayMaxSize*2; i < n; i++ { + data.b.Add(uint64(i * 3)) + } + } + + // Reset timer & benchmark. + b.ResetTimer() + for i := 0; i < b.N; i++ { + data.a.IntersectionCount(data.b) + } +} + +const ( + NumRows = uint64(10000) + NumColums = uint64(4) + MaxContainerVal = 0xffff +) + +func BenchmarkContainerLinear(b *testing.B) { + // run the Fib function b.N times + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + for row := uint64(0); row < NumRows; row++ { + for col := uint64(0); col < NumColums; col += 1 { + b.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) + } + } + } +} + +func BenchmarkContainerReverse(b *testing.B) { + // run the Fib function b.N times + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + for row := NumRows; row > 0; row-- { + for col := NumColums; col > 0; col -= 1 { + b.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) + } + } + } +} + +func BenchmarkContainerColumn(b *testing.B) { + // run the Fib function b.N times + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + for col := uint64(0); col < NumColums; col += 1 { + for row := uint64(0); row < NumRows; row++ { + b.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) + } + } + } +} + +func BenchmarkContainerOutsideIn(b *testing.B) { + // run the Fib function b.N times + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + + for col := uint64(0); col < NumColums; col += 1 { + for row := uint64(0); row < (NumRows - row); row++ { + b.Add(row*pilosa.SliceWidth + (col * pilosa.SliceWidth)) + b.Add((NumRows-row)*pilosa.SliceWidth + (col * MaxContainerVal)) + } + } + } +} + +func BenchmarkContainerInsideOut(b *testing.B) { + // run the Fib function b.N times + middle := NumRows / uint64(2) + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + for col := uint64(0); col < NumColums; col += uint64(1) { + for row := uint64(0); row < middle; row++ { + b.Add((middle+row)*pilosa.SliceWidth + (col * MaxContainerVal)) + b.Add((middle-row)*pilosa.SliceWidth + (col * MaxContainerVal)) + } + } + } +} + +func BenchmarkSLiceAscending(b *testing.B) { + // run the Fib function b.N times + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + for col := uint64(0); col < pilosa.SliceWidth; col++ { + b.Add(col) + } + } +} + +func BenchmarkSLiceDescending(b *testing.B) { + // run the Fib function b.N times + for n := 0; n < b.N; n++ { + b := roaring.NewBitmap() + for col := uint64(pilosa.SliceWidth); col > uint64(0); col-- { + b.Add(col) + } + } +} From a2195396ca8165032d41b815a920e3ac23a3c976 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Mon, 18 Dec 2017 15:01:52 -0600 Subject: [PATCH 2/8] fixed varible overwrite --- roaring/roaring_test.go | 51 +++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index 2a86c770a..b346fe7fd 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1145,85 +1145,80 @@ const ( ) func BenchmarkContainerLinear(b *testing.B) { - // run the Fib function b.N times + for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() + bm := roaring.NewBitmap() for row := uint64(0); row < NumRows; row++ { for col := uint64(0); col < NumColums; col += 1 { - b.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) + bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } } } func BenchmarkContainerReverse(b *testing.B) { - // run the Fib function b.N times for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() + bm := roaring.NewBitmap() for row := NumRows; row > 0; row-- { - for col := NumColums; col > 0; col -= 1 { - b.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) + for col := NumColums; col > 0; col-- { + bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } } } func BenchmarkContainerColumn(b *testing.B) { - // run the Fib function b.N times for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() - for col := uint64(0); col < NumColums; col += 1 { + bm := roaring.NewBitmap() + for col := uint64(0); col < NumColums; col++ { for row := uint64(0); row < NumRows; row++ { - b.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) + bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } } } func BenchmarkContainerOutsideIn(b *testing.B) { - // run the Fib function b.N times + middle := NumRows / uint64(2) for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() + bm := roaring.NewBitmap() - for col := uint64(0); col < NumColums; col += 1 { - for row := uint64(0); row < (NumRows - row); row++ { - b.Add(row*pilosa.SliceWidth + (col * pilosa.SliceWidth)) - b.Add((NumRows-row)*pilosa.SliceWidth + (col * MaxContainerVal)) + for col := uint64(0); col < NumColums; col++ { + for row := uint64(0); row < middle; row++ { + bm.Add(row*pilosa.SliceWidth + (col * pilosa.SliceWidth)) + bm.Add((NumRows-row)*pilosa.SliceWidth + (col * MaxContainerVal)) } } } } func BenchmarkContainerInsideOut(b *testing.B) { - // run the Fib function b.N times middle := NumRows / uint64(2) for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() - for col := uint64(0); col < NumColums; col += uint64(1) { + bm := roaring.NewBitmap() + for col := uint64(0); col < NumColums; col++ { for row := uint64(0); row < middle; row++ { - b.Add((middle+row)*pilosa.SliceWidth + (col * MaxContainerVal)) - b.Add((middle-row)*pilosa.SliceWidth + (col * MaxContainerVal)) + bm.Add((middle+row)*pilosa.SliceWidth + (col * MaxContainerVal)) + bm.Add((middle-row)*pilosa.SliceWidth + (col * MaxContainerVal)) } } } } func BenchmarkSLiceAscending(b *testing.B) { - // run the Fib function b.N times for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() + bm := roaring.NewBitmap() for col := uint64(0); col < pilosa.SliceWidth; col++ { - b.Add(col) + bm.Add(col) } } } func BenchmarkSLiceDescending(b *testing.B) { - // run the Fib function b.N times for n := 0; n < b.N; n++ { - b := roaring.NewBitmap() + bm := roaring.NewBitmap() for col := uint64(pilosa.SliceWidth); col > uint64(0); col-- { - b.Add(col) + bm.Add(col) } } } From 89a42c7fe2c47ca86ba9b4cacbf71f0effc1b26f Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Mon, 18 Dec 2017 15:18:54 -0600 Subject: [PATCH 3/8] corrected offset value --- roaring/roaring_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index b346fe7fd..c2bf3bca3 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1149,7 +1149,7 @@ func BenchmarkContainerLinear(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() for row := uint64(0); row < NumRows; row++ { - for col := uint64(0); col < NumColums; col += 1 { + for col := uint64(0); col < NumColums; col++ { bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } @@ -1185,7 +1185,7 @@ func BenchmarkContainerOutsideIn(b *testing.B) { for col := uint64(0); col < NumColums; col++ { for row := uint64(0); row < middle; row++ { - bm.Add(row*pilosa.SliceWidth + (col * pilosa.SliceWidth)) + bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) bm.Add((NumRows-row)*pilosa.SliceWidth + (col * MaxContainerVal)) } } From ccf57e23cd646ce8f0209ccd81c9952b76f78634 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Mon, 18 Dec 2017 15:33:22 -0600 Subject: [PATCH 4/8] removed overlap calc --- roaring/roaring_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index c2bf3bca3..a8f8bab84 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1197,7 +1197,7 @@ func BenchmarkContainerInsideOut(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() for col := uint64(0); col < NumColums; col++ { - for row := uint64(0); row < middle; row++ { + for row := uint64(1); row <= middle; row++ { bm.Add((middle+row)*pilosa.SliceWidth + (col * MaxContainerVal)) bm.Add((middle-row)*pilosa.SliceWidth + (col * MaxContainerVal)) } From 0f3d26bd30c391de42118761907bf6aa280ce9ac Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Tue, 19 Dec 2017 07:15:40 -0600 Subject: [PATCH 5/8] addressed jaffee suggestions; tweaked parameters --- roaring/roaring_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index a8f8bab84..a3d47cfe6 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1120,13 +1120,13 @@ func BenchmarkBitmap_IntersectionCount_ArrayBitmap(b *testing.B) { // Build bitmap with array container. data.a = roaring.NewBitmap() - for i, n := 0, rand.Intn(roaring.ArrayMaxSize); i < n; i++ { + for i, n := 0, 2*roaring.ArrayMaxSize/3; i < n; i++ { data.a.Add(uint64(rand.Intn(max))) } // Build bitmap with bitmap container. data.b = roaring.NewBitmap() - for i, n := 0, roaring.ArrayMaxSize*2; i < n; i++ { + for i, n := 0, MaxContainerVal/3; i < n; i++ { data.b.Add(uint64(i * 3)) } } @@ -1140,7 +1140,7 @@ func BenchmarkBitmap_IntersectionCount_ArrayBitmap(b *testing.B) { const ( NumRows = uint64(10000) - NumColums = uint64(4) + NumColums = uint64(16) MaxContainerVal = 0xffff ) @@ -1205,7 +1205,7 @@ func BenchmarkContainerInsideOut(b *testing.B) { } } -func BenchmarkSLiceAscending(b *testing.B) { +func BenchmarkSliceAscending(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() for col := uint64(0); col < pilosa.SliceWidth; col++ { @@ -1214,7 +1214,7 @@ func BenchmarkSLiceAscending(b *testing.B) { } } -func BenchmarkSLiceDescending(b *testing.B) { +func BenchmarkSliceDescending(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() for col := uint64(pilosa.SliceWidth); col > uint64(0); col-- { From 4ceaed53160c2082ac45767f81f54ffebd6c443b Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Tue, 19 Dec 2017 07:21:24 -0600 Subject: [PATCH 6/8] missed one --- roaring/roaring_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index a3d47cfe6..78056deb4 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1159,7 +1159,7 @@ func BenchmarkContainerLinear(b *testing.B) { func BenchmarkContainerReverse(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() - for row := NumRows; row > 0; row-- { + for row := NumRows - 1; row > 0; row-- { for col := NumColums; col > 0; col-- { bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } From d0d6d3d6b6203f0ba322ef12d0495cd61810185f Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Tue, 19 Dec 2017 07:52:53 -0600 Subject: [PATCH 7/8] added benchmarks for runs for intersect count --- roaring/roaring_test.go | 63 ++++++++++++++++++++++++++++++----------- 1 file changed, 46 insertions(+), 17 deletions(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index 78056deb4..546683a00 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1059,7 +1059,34 @@ func TestBitmapBufIterator(t *testing.T) { } var benchmarkBitmapIntersectionCountData struct { - a, b *roaring.Bitmap + a, b, r *roaring.Bitmap +} + +func getBenchData() *struct{ a, b, r *roaring.Bitmap } { + data := &benchmarkBitmapIntersectionCountData + if data.a == nil { + const max = (1 << 24) / 64 + + // Build bitmap with array container. + data.a = roaring.NewBitmap() + for i, n := 0, 2*roaring.ArrayMaxSize/3; i < n; i++ { + data.a.Add(uint64(rand.Intn(max))) + } + + // Build bitmap with bitmap container. + data.b = roaring.NewBitmap() + for i, n := 0, MaxContainerVal/3; i < n; i++ { + data.b.Add(uint64(i * 3)) + } + + // build bitmap with run container + data.r = roaring.NewBitmap() + for i, n := 0, MaxContainerVal; i < n; i++ { + data.r.Add(uint64(i)) + } + + } + return data } // GenerateUint64Slice generates between [0, n) random uint64 numbers between min and max. @@ -1113,24 +1140,26 @@ func TestBitmap_Intersect(t *testing.T) { } } -func BenchmarkBitmap_IntersectionCount_ArrayBitmap(b *testing.B) { - data := &benchmarkBitmapIntersectionCountData - if data.a == nil { - const max = (1 << 24) / 64 - - // Build bitmap with array container. - data.a = roaring.NewBitmap() - for i, n := 0, 2*roaring.ArrayMaxSize/3; i < n; i++ { - data.a.Add(uint64(rand.Intn(max))) - } - - // Build bitmap with bitmap container. - data.b = roaring.NewBitmap() - for i, n := 0, MaxContainerVal/3; i < n; i++ { - data.b.Add(uint64(i * 3)) - } +func BenchmarkBitmap_IntersectionCount_ArrayRun(b *testing.B) { + data := getBenchData() + // Reset timer & benchmark. + b.ResetTimer() + for i := 0; i < b.N; i++ { + data.a.IntersectionCount(data.r) } +} +func BenchmarkBitmap_IntersectionCount_BitmapRun(b *testing.B) { + data := getBenchData() + // Reset timer & benchmark. + b.ResetTimer() + for i := 0; i < b.N; i++ { + data.b.IntersectionCount(data.r) + } +} + +func BenchmarkBitmap_IntersectionCount_ArrayBitmap(b *testing.B) { + data := getBenchData() // Reset timer & benchmark. b.ResetTimer() for i := 0; i < b.N; i++ { From 1dbe64da3c46e4aa1c3793a091b6876711049bd6 Mon Sep 17 00:00:00 2001 From: Todd Gruben Date: Tue, 19 Dec 2017 10:45:27 -0600 Subject: [PATCH 8/8] made sure Linear and Reverse delt with same bits --- roaring/roaring_test.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/roaring/roaring_test.go b/roaring/roaring_test.go index 546683a00..6378ee67f 100644 --- a/roaring/roaring_test.go +++ b/roaring/roaring_test.go @@ -1177,8 +1177,8 @@ func BenchmarkContainerLinear(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() - for row := uint64(0); row < NumRows; row++ { - for col := uint64(0); col < NumColums; col++ { + for row := uint64(1); row < NumRows; row++ { + for col := uint64(1); col < NumColums; col++ { bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } @@ -1188,8 +1188,8 @@ func BenchmarkContainerLinear(b *testing.B) { func BenchmarkContainerReverse(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() - for row := NumRows - 1; row > 0; row-- { - for col := NumColums; col > 0; col-- { + for row := NumRows - 1; row >= 1; row-- { + for col := NumColums - 1; col >= 1; col-- { bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } @@ -1199,8 +1199,8 @@ func BenchmarkContainerReverse(b *testing.B) { func BenchmarkContainerColumn(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() - for col := uint64(0); col < NumColums; col++ { - for row := uint64(0); row < NumRows; row++ { + for col := uint64(1); col < NumColums; col++ { + for row := uint64(1); row < NumRows; row++ { bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) } } @@ -1212,8 +1212,8 @@ func BenchmarkContainerOutsideIn(b *testing.B) { for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() - for col := uint64(0); col < NumColums; col++ { - for row := uint64(0); row < middle; row++ { + for col := uint64(1); col < NumColums; col++ { + for row := uint64(1); row < middle; row++ { bm.Add(row*pilosa.SliceWidth + (col * MaxContainerVal)) bm.Add((NumRows-row)*pilosa.SliceWidth + (col * MaxContainerVal)) } @@ -1225,7 +1225,7 @@ func BenchmarkContainerInsideOut(b *testing.B) { middle := NumRows / uint64(2) for n := 0; n < b.N; n++ { bm := roaring.NewBitmap() - for col := uint64(0); col < NumColums; col++ { + for col := uint64(1); col < NumColums; col++ { for row := uint64(1); row <= middle; row++ { bm.Add((middle+row)*pilosa.SliceWidth + (col * MaxContainerVal)) bm.Add((middle-row)*pilosa.SliceWidth + (col * MaxContainerVal))