From 94c3d6f7a6c13b8b1e02e3b174f6117d6a4d8ba0 Mon Sep 17 00:00:00 2001 From: Andrzej Liszka Date: Mon, 30 Dec 2024 16:44:56 +0100 Subject: [PATCH] impr --- bitmap_opt.go | 68 ++++++++++++++-------------------------------- bitmap_opt_test.go | 16 ++++++++--- 2 files changed, 33 insertions(+), 51 deletions(-) diff --git a/bitmap_opt.go b/bitmap_opt.go index 6f9bb4b..65b1410 100644 --- a/bitmap_opt.go +++ b/bitmap_opt.go @@ -74,41 +74,9 @@ func (ra *Bitmap) AndConc(bm *Bitmap, maxConcurrency int) *Bitmap { return ra } - an := ra.keys.numKeys() - concurrency := an / minContainersPerRoutine - if concurrency < 1 || maxConcurrency == 1 { - concurrency = 1 - } else if maxConcurrency > 1 && maxConcurrency < concurrency { - concurrency = maxConcurrency - } - - if concurrency <= 1 { - andContainersInRange(ra, bm, 0, an, nil) - } else { - div := an / concurrency - mod := an % concurrency - - wg := new(sync.WaitGroup) - wg.Add(concurrency) - - for i := 0; i < concurrency; i++ { - var ai, aj int - - if i < mod { - ai = i * (div + 1) - aj = (i + 1) * (div + 1) - } else { - ai = mod*(div+1) + (i-mod)*div - aj = mod*(div+1) + (i-mod+1)*div - } - - go func() { - andContainersInRange(ra, bm, ai, aj, nil) - wg.Done() - }() - } - wg.Wait() - } + concurrentlyInRanges(ra.keys.numKeys(), minContainersPerRoutine, maxConcurrency, func(_, ai, aj int) { + andContainersInRange(ra, bm, ai, aj, nil) + }) return ra } @@ -264,8 +232,14 @@ func (ra *Bitmap) AndNotConc(bm *Bitmap, maxConcurrency int) *Bitmap { return ra } - bn := bm.keys.numKeys() - concurrency := bn / minContainersPerRoutine + concurrentlyInRanges(bm.keys.numKeys(), minContainersPerRoutine, maxConcurrency, func(_, bi, bj int) { + andNotContainersInRange(ra, bm, bi, bj, nil) + }) + return ra +} + +func concurrentlyInRanges(countElems, minElems, maxConcurrency int, callback func(i, from, to int)) { + concurrency := countElems / minElems if concurrency < 1 || maxConcurrency == 1 { concurrency = 1 } else if maxConcurrency > 1 && maxConcurrency < concurrency { @@ -273,33 +247,33 @@ func (ra *Bitmap) AndNotConc(bm *Bitmap, maxConcurrency int) *Bitmap { } if concurrency <= 1 { - andNotContainersInRange(ra, bm, 0, bn, nil) + callback(0, 0, countElems) } else { - div := bn / concurrency - mod := bn % concurrency + div := countElems / concurrency + mod := countElems % concurrency wg := new(sync.WaitGroup) wg.Add(concurrency) for i := 0; i < concurrency; i++ { - var bi, bj int + i := i + var from, to int if i < mod { - bi = i * (div + 1) - bj = (i + 1) * (div + 1) + from = i * (div + 1) + to = (i + 1) * (div + 1) } else { - bi = mod*(div+1) + (i-mod)*div - bj = mod*(div+1) + (i-mod+1)*div + from = mod*(div+1) + (i-mod)*div + to = mod*(div+1) + (i-mod+1)*div } go func() { - andNotContainersInRange(ra, bm, bi, bj, nil) + callback(i, from, to) wg.Done() }() } wg.Wait() } - return ra } func (ra *Bitmap) AndNotBuf(bm *Bitmap, buf []uint16) *Bitmap { diff --git a/bitmap_opt_test.go b/bitmap_opt_test.go index 4a78c78..2cb5e78 100644 --- a/bitmap_opt_test.go +++ b/bitmap_opt_test.go @@ -691,16 +691,16 @@ func TestCompareMergeImplementationsConcurrent(t *testing.T) { bm2 := NewBitmap() bm3 := NewBitmap() - for i := 0; i < 24000; i++ { + for i := 0; i < 20000; i++ { x := uint64(rnd.Int63n(int64(maxX))) - switch i % 6 { + switch i % 5 { case 0: bm1.Set(x) bm2.Set(x) - case 2: + case 1: bm2.Set(x) bm3.Set(x) - case 4: + case 2: bm1.Set(x) bm3.Set(x) default: @@ -717,6 +717,14 @@ func TestCompareMergeImplementationsConcurrent(t *testing.T) { require.Equal(t, bmAnd.GetCardinality(), bmAndConc.GetCardinality()) require.ElementsMatch(t, bmAnd.ToArray(), bmAndConc.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) + + require.Equal(t, bmAndNot.GetCardinality(), bmAndNotConc.GetCardinality()) + require.ElementsMatch(t, bmAndNot.ToArray(), bmAndNotConc.ToArray()) + }) } // checks if all exclusive containers from src bitmap