Skip to content

Commit

Permalink
wip4
Browse files Browse the repository at this point in the history
  • Loading branch information
aliszka committed Dec 31, 2024
1 parent b0cd9dc commit cc84c05
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 29 deletions.
84 changes: 61 additions & 23 deletions bitmap_opt.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,29 +66,42 @@ func (ra *Bitmap) And(bm *Bitmap) *Bitmap {
return ra
}

func (ra *Bitmap) AndConc(bm *Bitmap, maxConcurrency int) *Bitmap {
func (ra *Bitmap) AndBuf(bm *Bitmap, buf []uint16) *Bitmap {
assert(len(buf) == maxContainerSize)

if bm.IsEmpty() {
ra.Reset()
return ra
}

numContainers := ra.keys.numKeys()
concurrency := calcConcurrency(numContainers, minContainersPerRoutine, maxConcurrency)
callback := func(ai, aj, _ int) { andContainersInRange(ra, bm, ai, aj, nil) }
concurrentlyInRanges(numContainers, concurrency, callback)

andContainersInRange(ra, bm, 0, ra.keys.numKeys(), buf)
return ra
}

func (ra *Bitmap) AndBuf(bm *Bitmap, buf []uint16) *Bitmap {
assert(len(buf) == maxContainerSize)
func (ra *Bitmap) AndConc(bm *Bitmap, maxConcurrency int) *Bitmap {
return ra.andConc(bm, maxConcurrency, func(_ int) []uint16 { return nil })
}

func (ra *Bitmap) AndConcBuf(bm *Bitmap, bufs ...[]uint16) *Bitmap {
numBufs := len(bufs)
assert(numBufs > 0)
for i := range bufs {
assert(len(bufs[i]) == maxContainerSize)
}

return ra.andConc(bm, numBufs, func(i int) []uint16 { return bufs[i] })
}

func (ra *Bitmap) andConc(bm *Bitmap, maxConcurrency int, getBuf func(i int) []uint16) *Bitmap {
if bm.IsEmpty() {
ra.Reset()
return ra
}

andContainersInRange(ra, bm, 0, ra.keys.numKeys(), buf)
numContainers := ra.keys.numKeys()
concurrency := calcConcurrency(numContainers, minContainersPerRoutine, maxConcurrency)
callback := func(ai, aj, i int) { andContainersInRange(ra, bm, ai, aj, getBuf(i)) }
concurrentlyInRanges(numContainers, concurrency, callback)
return ra
}

Expand Down Expand Up @@ -227,27 +240,40 @@ func (ra *Bitmap) AndNot(bm *Bitmap) *Bitmap {
return ra
}

func (ra *Bitmap) AndNotConc(bm *Bitmap, maxConcurrency int) *Bitmap {
func (ra *Bitmap) AndNotBuf(bm *Bitmap, buf []uint16) *Bitmap {
assert(len(buf) == maxContainerSize)

if bm.IsEmpty() || ra.IsEmpty() {
return ra
}

numContainers := bm.keys.numKeys()
concurrency := calcConcurrency(numContainers, minContainersPerRoutine, maxConcurrency)
callback := func(bi, bj, _ int) { andNotContainersInRange(ra, bm, bi, bj, nil) }
concurrentlyInRanges(numContainers, concurrency, callback)

andNotContainersInRange(ra, bm, 0, bm.keys.numKeys(), buf)
return ra
}

func (ra *Bitmap) AndNotBuf(bm *Bitmap, buf []uint16) *Bitmap {
assert(len(buf) == maxContainerSize)
func (ra *Bitmap) AndNotConc(bm *Bitmap, maxConcurrency int) *Bitmap {
return ra.andNotConc(bm, maxConcurrency, func(_ int) []uint16 { return nil })
}

func (ra *Bitmap) AndNotConcBuf(bm *Bitmap, bufs ...[]uint16) *Bitmap {
numBufs := len(bufs)
assert(numBufs > 0)
for i := range bufs {
assert(len(bufs[i]) == maxContainerSize)
}

return ra.andNotConc(bm, numBufs, func(i int) []uint16 { return bufs[i] })
}

func (ra *Bitmap) andNotConc(bm *Bitmap, maxConcurrency int, getBuf func(i int) []uint16) *Bitmap {
if bm.IsEmpty() || ra.IsEmpty() {
return ra
}

andNotContainersInRange(ra, bm, 0, bm.keys.numKeys(), buf)
numContainers := bm.keys.numKeys()
concurrency := calcConcurrency(numContainers, minContainersPerRoutine, maxConcurrency)
callback := func(bi, bj, i int) { andNotContainersInRange(ra, bm, bi, bj, getBuf(i)) }
concurrentlyInRanges(numContainers, concurrency, callback)
return ra
}

Expand Down Expand Up @@ -501,6 +527,20 @@ func orContainersInRange(a, b *Bitmap, bi, bn int, buf []uint16) {
}

func (ra *Bitmap) OrConc(bm *Bitmap, maxConcurrency int) *Bitmap {
return ra.orConc(bm, maxConcurrency, func(_ int) []uint16 { return make([]uint16, maxContainerSize) })
}

func (ra *Bitmap) OrConcBuf(bm *Bitmap, bufs ...[]uint16) *Bitmap {
numBufs := len(bufs)
assert(numBufs > 0)
for i := range bufs {
assert(len(bufs[i]) == maxContainerSize)
}

return ra.orConc(bm, numBufs, func(i int) []uint16 { return bufs[i] })
}

func (ra *Bitmap) orConc(bm *Bitmap, maxConcurrency int, getBuf func(i int) []uint16) *Bitmap {
if bm.IsEmpty() {
return ra
}
Expand All @@ -509,8 +549,7 @@ func (ra *Bitmap) OrConc(bm *Bitmap, maxConcurrency int) *Bitmap {
concurrency := calcConcurrency(numContainers, minContainersPerRoutine, maxConcurrency)

if concurrency <= 1 {
buf := make([]uint16, maxContainerSize)
orContainersInRange(ra, bm, 0, numContainers, buf)
orContainersInRange(ra, bm, 0, numContainers, getBuf(0))
return ra
}

Expand All @@ -519,9 +558,8 @@ func (ra *Bitmap) OrConc(bm *Bitmap, maxConcurrency int) *Bitmap {
var allContainers [][]uint16
lock := new(sync.Mutex)
inlineVsMutateLock := new(sync.RWMutex)
callback := func(bi, bj, _ int) {
buf := make([]uint16, maxContainerSize)
sizeContainers, sizeKeys, keys, containers := orContainersInRangeConc(ra, bm, bi, bj, buf, inlineVsMutateLock)
callback := func(bi, bj, i int) {
sizeContainers, sizeKeys, keys, containers := orContainersInRangeConc(ra, bm, bi, bj, getBuf(i), inlineVsMutateLock)

lock.Lock()
totalSizeContainers += sizeContainers
Expand Down
36 changes: 30 additions & 6 deletions bitmap_opt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -691,6 +691,12 @@ func TestCompareMergeImplementationsConcurrent(t *testing.T) {
bm2 := NewBitmap()
bm3 := NewBitmap()

bufs8 := make([][]uint16, 8)
for i := range bufs8 {
bufs8[i] = make([]uint16, maxContainerSize)
}
bufs4 := bufs8[:4]

for i := 0; i < 20000; i++ {
x := uint64(rnd.Int63n(int64(maxX)))
switch i % 5 {
Expand All @@ -713,25 +719,43 @@ func TestCompareMergeImplementationsConcurrent(t *testing.T) {
t.Run("and", func(t *testing.T) {
bmAnd := bm1.Clone().And(bm2).And(bm3)
bmAndConc := bm1.Clone().AndConc(bm2, 4).AndConc(bm3, 8)
bmAndConcBuf := bm1.Clone().AndConcBuf(bm2, bufs4...).AndConcBuf(bm3, bufs8...)

card := bmAnd.GetCardinality()
arr := bmAnd.ToArray()

require.Equal(t, bmAnd.GetCardinality(), bmAndConc.GetCardinality())
require.ElementsMatch(t, bmAnd.ToArray(), bmAndConc.ToArray())
require.Equal(t, card, bmAndConc.GetCardinality())
require.Equal(t, card, bmAndConcBuf.GetCardinality())
require.ElementsMatch(t, arr, bmAndConc.ToArray())
require.ElementsMatch(t, arr, bmAndConcBuf.ToArray())
})

t.Run("and not", func(t *testing.T) {
bmAndNot := bm1.Clone().AndNot(bm2).AndNot(bm3)
bmAndNotConc := bm1.Clone().AndNotConc(bm2, 4).AndNotConc(bm3, 8)
bmAndNotConcBuf := bm1.Clone().AndNotConcBuf(bm2, bufs4...).AndNotConcBuf(bm3, bufs8...)

require.Equal(t, bmAndNot.GetCardinality(), bmAndNotConc.GetCardinality())
require.ElementsMatch(t, bmAndNot.ToArray(), bmAndNotConc.ToArray())
card := bmAndNot.GetCardinality()
arr := bmAndNot.ToArray()

require.Equal(t, card, bmAndNotConc.GetCardinality())
require.Equal(t, card, bmAndNotConcBuf.GetCardinality())
require.ElementsMatch(t, arr, bmAndNotConc.ToArray())
require.ElementsMatch(t, arr, bmAndNotConcBuf.ToArray())
})

t.Run("or", func(t *testing.T) {
bmOr := bm1.Clone().Or(bm2).Or(bm3)
bmOrConc := bm1.Clone().OrConc(bm2, 4).OrConc(bm3, 8)
bmOrConcBuf := bm1.Clone().OrConcBuf(bm2, bufs4...).OrConcBuf(bm3, bufs8...)

card := bmOr.GetCardinality()
arr := bmOr.ToArray()

require.Equal(t, bmOr.GetCardinality(), bmOrConc.GetCardinality())
require.ElementsMatch(t, bmOr.ToArray(), bmOrConc.ToArray())
require.Equal(t, card, bmOrConc.GetCardinality())
require.Equal(t, card, bmOrConcBuf.GetCardinality())
require.ElementsMatch(t, arr, bmOrConc.ToArray())
require.ElementsMatch(t, arr, bmOrConcBuf.ToArray())
})
}

Expand Down

0 comments on commit cc84c05

Please sign in to comment.