diff --git a/fragment_internal_test.go b/fragment_internal_test.go index 548e5f40a..ce7e06da9 100644 --- a/fragment_internal_test.go +++ b/fragment_internal_test.go @@ -2572,3 +2572,29 @@ func TestFragmentRowIterator(t *testing.T) { } }) } + +func TestUnionInPlaceMapped(t *testing.T) { + f := mustOpenFragment("i", "f", "v", 0, CacheTypeNone) + defer f.Clean(t) + r0 := rand.New(rand.NewSource(2)) + r1 := rand.New(rand.NewSource(1)) + data0 := randPositions(1000000, r0) + setBM := roaring.NewBitmap() + setBM.OpWriter = nil + setBM.Add(data0...) + unprotectedWriteToFragment(f, setBM) + data1 := randPositions(1000000, r1) + setBM2 := roaring.NewBitmap() + setBM2.OpWriter = nil + setBM2.Add(data1...) + + f.storage.UnionInPlace(setBM2) +} + +func randPositions(n int, r *rand.Rand) []uint64 { + ret := make([]uint64, n) + for i := 0; i < n; i++ { + ret[i] = uint64(r.Int63n(ShardWidth)) + } + return ret +} diff --git a/roaring/roaring.go b/roaring/roaring.go index a34d9347e..818184148 100644 --- a/roaring/roaring.go +++ b/roaring/roaring.go @@ -2720,6 +2720,7 @@ func unionBitmapRun(a, b *Container) *Container { // unions the run b into the bitmap a, mutating a in place. The n value of // a will need to be repaired after the fact. func unionBitmapRunInPlace(a, b *Container) { + a.unmap() statsHit("union/BitmapRun") for j := 0; j < len(b.runs); j++ { a.bitmapSetRangeIgnoreN(uint64(b.runs[j].start), uint64(b.runs[j].last)+1) @@ -2867,6 +2868,7 @@ func unionArrayBitmap(a, b *Container) *Container { // unions array b into bitmap a, mutating a in place. The n value // of a will need to be repaired after the fact. func unionBitmapArrayInPlace(a, b *Container) { + a.unmap() for _, v := range b.array { a.bitmap[v>>6] |= (uint64(1) << (v % 64)) } @@ -2901,6 +2903,8 @@ func unionBitmapBitmap(a, b *Container) *Container { // unions bitmap b into bitmap a, mutating a in place. The n value of // a will need to be repaired after the fact. func unionBitmapBitmapInPlace(a, b *Container) { + a.unmap() + // local variables added to prevent BCE checks in loop // see https://go101.org/article/bounds-check-elimination.html