diff --git a/roaring/roaring.go b/roaring/roaring.go index 7c64472e3..f24e13fdd 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -503,8 +503,16 @@ func (b *Bitmap) countEmptyContainers() int { return result } +// Optimize converts array and bitmap containers to run containers as necessary. +func (b *Bitmap) Optimize() { + for _, c := range b.containers { + c.Optimize() + } +} + // WriteTo writes b to w. func (b *Bitmap) WriteTo(w io.Writer) (n int64, err error) { + b.Optimize() // Remove empty containers before persisting. //b.removeEmptyContainers() containerCount := len(b.keys) - b.countEmptyContainers() @@ -1099,6 +1107,7 @@ func (c *container) arrayAdd(v uint32) bool { copy(c.array[i+1:], c.array[i:]) c.array[i] = v return true + } func (c *container) bitmapAdd(v uint32) bool { @@ -1185,6 +1194,20 @@ func (c *container) arrayCountRuns() (r int) { return r } +func (c *container) Optimize() { + if c.isArray() { + runs := c.arrayCountRuns() + if runs < c.n/2 { + c.arrayToRun() + } + } else if c.isBitmap() { + runs := c.bitmapCountRuns() + if runs < 2048 { + c.bitmapToRun() + } + } +} + func (c *container) arrayContains(v uint32) bool { return search32(c.array, v) >= 0 }