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 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") + } + } +}