rbf/intoContainer: ensure correct N, avoid recounting

The remake container logic (used to avoid allocating extra containers while
applying filters) relied on roaring recomputing N, which it did for bitmaps
but didn't do for runs. Fix this both ways; it would now do that for runs,
but also we add "with explicit N" variants and use those since we have a
correct count already, and don't need it. This means fewer popcounts on
bitmaps, and working at all on runs.
This commit is contained in:
Seebs 2021-04-12 16:13:16 -05:00
parent 84c269bfc0
commit 269837414e
2 changed files with 30 additions and 2 deletions

View file

@ -197,9 +197,9 @@ func intoContainer(l leafCell, tx *Tx, replacing *roaring.Container, target []by
}
c = roaring.RemakeContainerBitmap(replacing, cloneMaybe)
case ContainerTypeBitmap:
c = roaring.RemakeContainerBitmap(replacing, toArray64(cpMaybe))
c = roaring.RemakeContainerBitmapN(replacing, toArray64(cpMaybe), int32(l.BitN))
case ContainerTypeRLE:
c = roaring.RemakeContainerRun(replacing, toInterval16(cpMaybe))
c = roaring.RemakeContainerRunN(replacing, toInterval16(cpMaybe), int32(l.BitN))
}
// Note: If the "roaringparanoia" build tag isn't set, this
// should be optimized away entirely. Otherwise it's moderately

View file

@ -125,6 +125,8 @@ func NewContainer() *Container {
return NewContainerArray(nil)
}
// RemakeContainerBitmap overwrites the contents of c, which must not be
// frozen, with a provided bitmap, and computes a correct N.
func RemakeContainerBitmap(c *Container, bitmap []uint64) *Container {
*c = Container{typeID: ContainerBitmap}
c.setBitmap(bitmap)
@ -132,15 +134,41 @@ func RemakeContainerBitmap(c *Container, bitmap []uint64) *Container {
return c
}
// RemakeContainerBitmapN uses the provided n instead of counting bits. The
// provided container must not be frozen.
func RemakeContainerBitmapN(c *Container, bitmap []uint64, n int32) *Container {
*c = Container{typeID: ContainerBitmap}
c.setBitmap(bitmap)
c.n = n
return c
}
// RemakeContainerArray populates c with an array container using the provided
// array. It must not be used on a frozen container.
func RemakeContainerArray(c *Container, array []uint16) *Container {
*c = Container{typeID: ContainerArray}
c.setArray(array)
return c
}
// RemakeContainerRun repopulates c with the provided intervals. c must not
// be frozen.
func RemakeContainerRun(c *Container, intervals []Interval16) *Container {
*c = Container{typeID: ContainerRun}
c.setRuns(intervals)
c.n = 0
for _, r := range intervals {
c.n += int32(r.Last - r.Start + 1)
}
return c
}
// RemakeContainerRunN repopulates c with the provided intervals, but
// assumes the provided n is accurate. c must not be frozen.
func RemakeContainerRunN(c *Container, intervals []Interval16, n int32) *Container {
*c = Container{typeID: ContainerRun}
c.setRuns(intervals)
c.n = n
return c
}