From d82c20ddaf065bbf7427ab7a27a7bdd04e5cdaf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Senart?= Date: Sun, 17 Dec 2023 21:03:29 +0100 Subject: [PATCH] fixup! honor arrayDefaultMaxSize invariant MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` name \ time/op before with-efficient-container no-to-efficient-container FromDense/bitmap-4097-10 1.45µs ± 1% 2.15µs ± 0% 1.47µs ± 2% FromDense/run-4098-10 1.04µs ± 4% 3.00µs ± 0% 1.04µs ± 2% FromDense/array-4096-10 1.45µs ± 1% 6.47µs ± 8% 5.46µs ± 1% FromDense/bitmaps-and-runs-300000-10 3.53µs ± 0% 13.53µs ± 1% 3.57µs ± 1% name \ speed before with-efficient-container no-to-efficient-container FromDense/bitmap-4097-10 6.35GB/s ± 1% 4.28GB/s ± 0% 6.27GB/s ± 2% FromDense/run-4098-10 989MB/s ± 4% 345MB/s ± 0% 990MB/s ± 2% FromDense/array-4096-10 6.36GB/s ± 1% 1.43GB/s ± 8% 1.69GB/s ± 1% FromDense/bitmaps-and-runs-300000-10 15.9GB/s ± 0% 4.2GB/s ± 1% 15.8GB/s ± 1% name \ alloc/op before with-efficient-container no-to-efficient-container FromDense/bitmap-4097-10 8.22kB ± 0% 8.22kB ± 0% 8.22kB ± 0% FromDense/run-4098-10 8.22kB ± 0% 8.26kB ± 0% 8.22kB ± 0% FromDense/array-4096-10 8.22kB ± 0% 16.44kB ± 0% 16.41kB ± 0% FromDense/bitmaps-and-runs-300000-10 8.35kB ± 0% 8.49kB ± 0% 8.35kB ± 0% name \ allocs/op before with-efficient-container no-to-efficient-container FromDense/bitmap-4097-10 2.00 ± 0% 2.00 ± 0% 2.00 ± 0% FromDense/run-4098-10 2.00 ± 0% 4.00 ± 0% 2.00 ± 0% FromDense/array-4096-10 2.00 ± 0% 4.00 ± 0% 3.00 ± 0% FromDense/bitmaps-and-runs-300000-10 6.00 ± 0% 16.00 ± 0% 6.00 ± 0% ``` --- roaring.go | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/roaring.go b/roaring.go index 6dfe5cd1..4a617310 100644 --- a/roaring.go +++ b/roaring.go @@ -89,6 +89,8 @@ func (rb *Bitmap) ToDense() []uint64 { // FromDense creates a bitmap from a slice of uint64s representing the bitmap as a dense bitmap. // Useful to convert bitmaps from libraries like https://github.com/bits-and-blooms/bitset or // https://github.com/kelindar/bitmap into roaring bitmaps fast and with convenience. +// This function won't create any run containers, only array and bitmap containers. It's up to +// the caller to call RunOptimize if they want to further compress the runs of consecutive values. func FromDense(bitmap []uint64) *Bitmap { sz := (len(bitmap) + bitmapContainerSize - 1) / bitmapContainerSize // round up rb := &Bitmap{ @@ -106,6 +108,8 @@ func FromDense(bitmap []uint64) *Bitmap { // Useful to convert bitmaps from libraries like https://github.com/bits-and-blooms/bitset or // https://github.com/kelindar/bitmap into roaring bitmaps fast and with convenience. // Callers are responsible for ensuring that the bitmap is empty before calling this function. +// This function won't create any run containers, only array and bitmap containers. It's up to +// the caller to call RunOptimize if they want to further compress the runs of consecutive values. func (rb *Bitmap) FromDense(bitmap []uint64) { if len(bitmap) == 0 { return @@ -124,10 +128,24 @@ func (rb *Bitmap) FromDense(bitmap []uint64) { } words := bitmap[:size] - if count := int(popcntSlice(words)); count > 0 { - c := &bitmapContainer{ - bitmap: words, - cardinality: count, + count := int(popcntSlice(words)) + + switch { + case count > arrayDefaultMaxSize: + c := &bitmapContainer{bitmap: words, cardinality: count} + rb.highlowcontainer.appendContainer(k, c, cow) + + case count > 0: + c := &arrayContainer{content: make([]uint16, count)} + var pos, base int + for _, w := range words { + for w != 0 { + t := w & -w + c.content[pos] = uint16(base + int(popcount(t-1))) + pos++ + w ^= t + } + base += 64 } rb.highlowcontainer.appendContainer(k, c, cow) }