From 65603a1788b1e846259ec1ae4dda23f5c5298f0d Mon Sep 17 00:00:00 2001 From: Perfloop Agent Date: Wed, 19 Aug 2026 14:27:08 +0000 Subject: [PATCH 1/2] bench: cover roaring64 batch iteration --- roaring64/manyiterator_bench_test.go | 49 ++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 roaring64/manyiterator_bench_test.go diff --git a/roaring64/manyiterator_bench_test.go b/roaring64/manyiterator_bench_test.go new file mode 100644 index 00000000..ffb7c85d --- /dev/null +++ b/roaring64/manyiterator_bench_test.go @@ -0,0 +1,49 @@ +package roaring64 + +import "testing" + +const benchmarkRoaring64BatchCardinality = 1 << 15 + +func benchmarkRoaring64BatchBitmap() *Bitmap { + values := make([]uint64, benchmarkRoaring64BatchCardinality) + for i := range values { + values[i] = uint64(i * 2) + } + + bitmap := New() + bitmap.AddMany(values) + return bitmap +} + +func BenchmarkRoaring64ToArray(b *testing.B) { + bitmap := benchmarkRoaring64BatchBitmap() + last := uint64((benchmarkRoaring64BatchCardinality - 1) * 2) + + for b.Loop() { + values := bitmap.ToArray() + if len(values) != benchmarkRoaring64BatchCardinality || values[0] != 0 || values[len(values)-1] != last { + b.Fatal("unexpected bitmap contents") + } + } +} + +func BenchmarkRoaring64ManyIterator(b *testing.B) { + bitmap := benchmarkRoaring64BatchBitmap() + values := make([]uint64, benchmarkRoaring64BatchCardinality) + last := uint64((benchmarkRoaring64BatchCardinality - 1) * 2) + + for b.Loop() { + iterator := bitmap.ManyIterator() + n := 0 + for n < len(values) { + count := iterator.NextMany(values[n:]) + if count == 0 { + break + } + n += count + } + if n != len(values) || values[0] != 0 || values[n-1] != last { + b.Fatal("unexpected iterator contents") + } + } +} From 1215956941f6b60ed7481b802d4796a3b7560d9f Mon Sep 17 00:00:00 2001 From: Perfloop Agent Date: Wed, 19 Aug 2026 14:30:13 +0000 Subject: [PATCH 2/2] perf: optimize bitmap container batch iteration --- bitmapcontainer.go | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/bitmapcontainer.go b/bitmapcontainer.go index 416da732..1ef8e3e4 100644 --- a/bitmapcontainer.go +++ b/bitmapcontainer.go @@ -187,10 +187,17 @@ func (bcmi *bitmapContainerManyIterator) nextMany(hs uint32, buf []uint32) int { bitset = bcmi.ptr.bitmap[base] continue } - t := bitset & -bitset - buf[n] = uint32(((base * 64) + bits.OnesCount64(t-1))) | hs - n = n + 1 - bitset ^= t + if len(buf)-n >= 64 { + for bitset != 0 { + buf[n] = uint32((base*64)+bits.TrailingZeros64(bitset)) | hs + n++ + bitset &= bitset - 1 + } + continue + } + buf[n] = uint32((base*64)+bits.TrailingZeros64(bitset)) | hs + n++ + bitset &= bitset - 1 } bcmi.base = base @@ -215,10 +222,17 @@ func (bcmi *bitmapContainerManyIterator) nextMany64(hs uint64, buf []uint64) int bitset = bcmi.ptr.bitmap[base] continue } - t := bitset & -bitset - buf[n] = uint64(((base * 64) + bits.OnesCount64(t-1))) | hs - n = n + 1 - bitset ^= t + if len(buf)-n >= 64 { + for bitset != 0 { + buf[n] = uint64((base*64)+bits.TrailingZeros64(bitset)) | hs + n++ + bitset &= bitset - 1 + } + continue + } + buf[n] = uint64((base*64)+bits.TrailingZeros64(bitset)) | hs + n++ + bitset &= bitset - 1 } bcmi.base = base