Skip to content

Commit 835e6c2

Browse files
author
Peter Alfonsi
committed
Optimized modulo calculation with bitmask
Signed-off-by: Peter Alfonsi <[email protected]>
1 parent f5a0eb8 commit 835e6c2

File tree

2 files changed

+18
-3
lines changed

2 files changed

+18
-3
lines changed

server/src/main/java/org/opensearch/common/cache/tier/keystore/RBMIntKeyLookupStore.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ public int getValue() {
7272
}
7373

7474
protected final int modulo;
75+
protected final int modulo_bitmask;
76+
// Since our modulo is always a power of two we can optimize it by ANDing with a particular bitmask
7577
KeyStoreStats stats;
7678
protected RoaringBitmap rbm;
7779
private HashMap<Integer, CounterMetric> collidedIntCounters;
@@ -92,15 +94,20 @@ public RBMIntKeyLookupStore(long memSizeCapInBytes) {
9294

9395
public RBMIntKeyLookupStore(KeystoreModuloValue moduloValue, long memSizeCapInBytes) {
9496
this.modulo = moduloValue.getValue();
97+
if (modulo > 0) {
98+
this.modulo_bitmask = modulo - 1; // keep last log_2(modulo) bits
99+
} else {
100+
this.modulo_bitmask = -1; // -1 in twos complement is all ones -> includes all bits -> same as no modulo
101+
}
95102
this.stats = new KeyStoreStats(memSizeCapInBytes);
96103
this.rbm = new RoaringBitmap();
97104
this.collidedIntCounters = new HashMap<>();
98105
this.removalSets = new HashMap<>();
99106
this.mostRecentByteEstimate = 0L;
100107
}
101108

102-
private final int transform(int value) {
103-
return modulo == 0 ? value : value % modulo;
109+
private int transform(int value) {
110+
return value & modulo_bitmask;
104111
}
105112

106113
private void handleCollisions(int transformedValue) {

server/src/test/java/org/opensearch/common/cache/tier/keystore/RBMIntKeyLookupStoreTests.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,14 +61,22 @@ public void testTransformationLogic() throws Exception {
6161
for (int i = 0; i < 4; i++) { // after this we run into max value, but thats not a flaw with the class design
6262
int posValue = i * modulo + offset;
6363
kls.add(posValue);
64+
assertEquals(offset, (int) kls.getInternalRepresentation(posValue));
6465
int negValue = -(i * modulo + offset);
6566
kls.add(negValue);
67+
assertEquals(modulo - offset, (int) kls.getInternalRepresentation(negValue));
6668
}
6769
assertEquals(2, kls.getSize());
6870
int[] testVals = new int[] { 0, 1, -1, -23495, 23058, modulo, -modulo, Integer.MAX_VALUE, Integer.MIN_VALUE };
6971
for (int value : testVals) {
7072
assertTrue(kls.getInternalRepresentation(value) < modulo);
71-
assertTrue(kls.getInternalRepresentation(value) > -modulo);
73+
assertTrue(kls.getInternalRepresentation(value) >= 0);
74+
}
75+
RBMIntKeyLookupStore no_modulo_kls = new RBMIntKeyLookupStore(RBMIntKeyLookupStore.KeystoreModuloValue.NONE, 0L);
76+
Random rand = Randomness.get();
77+
for (int i = 0; i < 100; i++) {
78+
int val = rand.nextInt();
79+
assertEquals(val, (int) no_modulo_kls.getInternalRepresentation(val));
7280
}
7381
}
7482

0 commit comments

Comments
 (0)