BenchmarkCardinalityInRange compares CardinalityInRange vs the naïve Rank(end-1)-Rank(start-1) approach across different bitmap sizes and range widths to demonstrate the O(log n + k) vs O(n) difference.
(b *testing.B)
| 1309 | // across different bitmap sizes and range widths to demonstrate the O(log n + k) vs O(n) |
| 1310 | // difference. |
| 1311 | func BenchmarkCardinalityInRange(b *testing.B) { |
| 1312 | // Build bitmaps of varying sizes: each has numContainers containers with 100 values each. |
| 1313 | for _, numContainers := range []int{10, 100, 1000} { |
| 1314 | // Build the bitmap: numContainers containers, each with 100 values. |
| 1315 | rb := NewBitmap() |
| 1316 | for c := 0; c < numContainers; c++ { |
| 1317 | base := uint32(c) << 16 // each container has a different high-16-bit key |
| 1318 | for v := uint32(0); v < 100; v++ { |
| 1319 | rb.Add(base + v*10) |
| 1320 | } |
| 1321 | } |
| 1322 | |
| 1323 | for _, rangeContainers := range []int{1, 10, 100, 1000} { |
| 1324 | if rangeContainers > numContainers { |
| 1325 | continue |
| 1326 | } |
| 1327 | // Place the range in the middle of the bitmap so both methods do real work. |
| 1328 | mid := numContainers / 2 |
| 1329 | rangeStart := uint64(uint32(mid-(rangeContainers/2)) << 16) |
| 1330 | rangeEnd := uint64(uint32(mid+(rangeContainers+1)/2) << 16) |
| 1331 | |
| 1332 | label := fmt.Sprintf("containers=%d/rangeSpan=%d", numContainers, rangeContainers) |
| 1333 | |
| 1334 | b.Run(label+"/RankViaTwoRanks", func(b *testing.B) { |
| 1335 | b.ResetTimer() |
| 1336 | for i := 0; i < b.N; i++ { |
| 1337 | r := rb.Rank(uint32(rangeEnd - 1)) |
| 1338 | if rangeStart > 0 { |
| 1339 | r -= rb.Rank(uint32(rangeStart - 1)) |
| 1340 | } |
| 1341 | if r == 0 && numContainers == 0 { |
| 1342 | b.Fatal("unexpected") // prevent dead-code elimination |
| 1343 | } |
| 1344 | } |
| 1345 | }) |
| 1346 | |
| 1347 | b.Run(label+"/CardinalityInRange", func(b *testing.B) { |
| 1348 | b.ResetTimer() |
| 1349 | for i := 0; i < b.N; i++ { |
| 1350 | r := rb.CardinalityInRange(rangeStart, rangeEnd) |
| 1351 | if r == 0 && numContainers == 0 { |
| 1352 | b.Fatal("unexpected") // prevent dead-code elimination |
| 1353 | } |
| 1354 | } |
| 1355 | }) |
| 1356 | } |
| 1357 | } |
| 1358 | } |
| 1359 | |
| 1360 | // BenchmarkFastOrRunContainers measures FastOr over inputs containing |
| 1361 | // runContainer16 slots (the shape AddRange and RunOptimize produce), |
nothing calls this directly
no test coverage detected
searching dependent graphs…