Skip to content

Commit f147b93

Browse files
authored
Cache ImmutableRoaringBitmap in NullValueVectorReaderImpl to avoid repeated deserialization (#18145)
1 parent dcbe2ae commit f147b93

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

pinot-segment-local/src/main/java/org/apache/pinot/segment/local/segment/index/readers/NullValueVectorReaderImpl.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
public class NullValueVectorReaderImpl implements NullValueVectorReader {
2727

2828
private final PinotDataBuffer _dataBuffer;
29+
// Cached bitmap to avoid re-deserializing from the underlying buffer on every call.
30+
// ImmutableRoaringBitmap is thread-safe once constructed, so a volatile field is sufficient.
31+
private volatile ImmutableRoaringBitmap _nullBitmap;
2932

3033
public NullValueVectorReaderImpl(PinotDataBuffer dataBuffer) {
3134
_dataBuffer = dataBuffer;
@@ -37,6 +40,11 @@ public boolean isNull(int docId) {
3740

3841
@Override
3942
public ImmutableRoaringBitmap getNullBitmap() {
40-
return new ImmutableRoaringBitmap(_dataBuffer.toDirectByteBuffer(0, (int) _dataBuffer.size()));
43+
ImmutableRoaringBitmap nullBitmap = _nullBitmap;
44+
if (nullBitmap == null) {
45+
nullBitmap = new ImmutableRoaringBitmap(_dataBuffer.toDirectByteBuffer(0, (int) _dataBuffer.size()));
46+
_nullBitmap = nullBitmap;
47+
}
48+
return nullBitmap;
4149
}
4250
}

pinot-segment-local/src/test/java/org/apache/pinot/segment/local/segment/index/readers/NullValueVectorReaderImplTest.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,19 @@ public void testNullValueVectorReader()
6262
}
6363
}
6464

65+
@Test
66+
public void testNullBitmapIsCached()
67+
throws IOException {
68+
File nullValueFile = new File(TEMP_DIR, TEMP_DIR.list()[0]);
69+
try (PinotDataBuffer buffer = PinotDataBuffer.loadBigEndianFile(nullValueFile)) {
70+
NullValueVectorReaderImpl reader = new NullValueVectorReaderImpl(buffer);
71+
// Repeated calls to getNullBitmap() must return the same instance, not reconstruct it
72+
org.roaringbitmap.buffer.ImmutableRoaringBitmap first = reader.getNullBitmap();
73+
org.roaringbitmap.buffer.ImmutableRoaringBitmap second = reader.getNullBitmap();
74+
Assert.assertSame(first, second, "getNullBitmap() should return the cached instance on repeated calls");
75+
}
76+
}
77+
6578
@AfterClass
6679
public void tearDown()
6780
throws Exception {

0 commit comments

Comments
 (0)