Skip to content

Commit 442c0b9

Browse files
Small optimisation to store the mask. (#941)
* Small optimisation to store the mask. Have been chasing some optimisations and noticing getSlotAndOffset taking up reasonable cycles because it is used in some per packet path. Making a small optimisation to store the mask. * generated protobuf --------- Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
1 parent 5b4142c commit 442c0b9

File tree

2 files changed

+26
-26
lines changed

2 files changed

+26
-26
lines changed

utils/bitmap.go

Lines changed: 24 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,14 @@ type bitmapNumber interface {
2222

2323
type Bitmap[T bitmapNumber] struct {
2424
bits []uint64
25+
mask int
2526
}
2627

2728
func NewBitmap[T bitmapNumber](size int) *Bitmap[T] {
29+
numElems := 1 << bits.Len64(uint64(size+63)/64)
2830
return &Bitmap[T]{
29-
bits: make([]uint64, 1<<bits.Len64(uint64(size+63)/64)),
31+
bits: make([]uint64, numElems),
32+
mask: numElems - 1,
3033
}
3134
}
3235

@@ -35,64 +38,61 @@ func (b *Bitmap[T]) Len() int {
3538
}
3639

3740
func (b *Bitmap[T]) Set(val T) {
38-
sm, s, o := b.getSlotAndOffset(val)
39-
b.bits[s&sm] |= 1 << o
41+
s, o := b.getSlotAndOffset(val)
42+
b.bits[s&b.mask] |= 1 << o
4043
}
4144

4245
func (b *Bitmap[T]) SetRange(min, max T) {
4346
if max < min {
4447
return
4548
}
4649

47-
sm, ls, rs, lo, ro := b.getSlotsAndOffsets(min, max)
50+
ls, rs, lo, ro := b.getSlotsAndOffsets(min, max)
4851
if ls == rs {
49-
b.bits[ls&sm] |= (((1 << (ro - lo + 1)) - 1) << lo)
52+
b.bits[ls&b.mask] |= (((1 << (ro - lo + 1)) - 1) << lo)
5053
} else {
51-
b.bits[ls&sm] |= ^((1 << lo) - 1)
54+
b.bits[ls&b.mask] |= ^((1 << lo) - 1)
5255
for i := ls + 1; i < rs; i++ {
53-
b.bits[i&sm] = ^uint64(0)
56+
b.bits[i&b.mask] = ^uint64(0)
5457
}
55-
b.bits[rs&sm] |= (1 << (ro + 1)) - 1
58+
b.bits[rs&b.mask] |= (1 << (ro + 1)) - 1
5659
}
5760
}
5861

5962
func (b *Bitmap[T]) Clear(val T) {
60-
sm, s, o := b.getSlotAndOffset(val)
61-
b.bits[s&sm] &= ^(1 << o)
63+
s, o := b.getSlotAndOffset(val)
64+
b.bits[s&b.mask] &= ^(1 << o)
6265
}
6366

6467
func (b *Bitmap[T]) ClearRange(min, max T) {
6568
if max < min {
6669
return
6770
}
6871

69-
sm, ls, rs, lo, ro := b.getSlotsAndOffsets(min, max)
72+
ls, rs, lo, ro := b.getSlotsAndOffsets(min, max)
7073
if ls == rs {
71-
b.bits[ls&sm] &= ^(((1 << (ro - lo + 1)) - 1) << lo)
74+
b.bits[ls&b.mask] &= ^(((1 << (ro - lo + 1)) - 1) << lo)
7275
} else {
73-
b.bits[ls&sm] &= ^uint64(0) >> (64 - lo)
76+
b.bits[ls&b.mask] &= ^uint64(0) >> (64 - lo)
7477
for i := ls + 1; i < rs; i++ {
75-
b.bits[i&sm] = 0
78+
b.bits[i&b.mask] = 0
7679
}
77-
b.bits[rs&sm] &= ^uint64(0) << (ro + 1)
80+
b.bits[rs&b.mask] &= ^uint64(0) << (ro + 1)
7881
}
7982
}
8083

8184
func (b *Bitmap[T]) IsSet(val T) bool {
82-
sm, s, o := b.getSlotAndOffset(val)
83-
return b.bits[s&sm]&(1<<o) != 0
85+
s, o := b.getSlotAndOffset(val)
86+
return b.bits[s&b.mask]&(1<<o) != 0
8487
}
8588

86-
func (b *Bitmap[T]) getSlotAndOffset(val T) (sm, s, o int) {
87-
sm = len(b.bits) - 1 // slot mask
88-
s = int(val >> 6) // slot
89-
o = int(val & 0x3f) // offset
89+
func (b *Bitmap[T]) getSlotAndOffset(val T) (s, o int) {
90+
s = int(val >> 6) // slot
91+
o = int(val & 0x3f) // offset
9092
return
9193
}
9294

93-
func (b *Bitmap[T]) getSlotsAndOffsets(min, max T) (sm, ls, rs, lo, ro int) {
94-
sm = len(b.bits) - 1 // slot mask
95-
95+
func (b *Bitmap[T]) getSlotsAndOffsets(min, max T) (ls, rs, lo, ro int) {
9696
ls = int(min >> 6) // left slot
9797
rs = int(max >> 6) // right slot
9898

utils/bitmap_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,6 @@ func TestBitmap(t *testing.T) {
9494
require.Equal(t, e, b.bits)
9595

9696
// large range changes touch each word once
97-
sm, ls, rs, lo, ro := b.getSlotsAndOffsets(0, math.MaxUint32)
98-
require.Equal(t, []int{3, 0, 4, 0, 0}, []int{sm, ls, rs, lo, ro})
97+
ls, rs, lo, ro := b.getSlotsAndOffsets(0, math.MaxUint32)
98+
require.Equal(t, []int{0, 4, 0, 0}, []int{ls, rs, lo, ro})
9999
}

0 commit comments

Comments
 (0)