Add range mark query APIs to BitMap - #884
Conversation
| * | ||
| * @throws IndexOutOfBoundsException if the range is outside this bitmap | ||
| */ | ||
| public boolean isRangeAnyMarked(int start, int length) { |
There was a problem hiding this comment.
These public APIs distinguish any, all, and none semantics without forcing callers to scan individual bits. The Javadocs explicitly define empty-range results and preserve the existing bitmap range-error convention for invalid input.
|
|
||
| abstract boolean isMarked(int position); | ||
|
|
||
| boolean isRangeAnyMarked(int start, int length) { |
There was a problem hiding this comment.
The shared implementation keeps long-backed and byte-array-backed bitmaps behaviorally identical by reusing extractBits in batches of up to 64 bits. Range validation uses start > size - length instead of start + length > size so an overflowing sum cannot bypass the bounds check.
| } | ||
|
|
||
| @Test | ||
| public void testRangeMarkedQueries() { |
There was a problem hiding this comment.
This test checks every valid subrange against a per-bit oracle for empty, array-backed, and long-backed bitmaps, including ranges that cross byte and 64-bit boundaries. It also verifies negative, out-of-bounds, and integer-overflow arguments.
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## develop #884 +/- ##
===========================================
- Coverage 60.51% 60.46% -0.06%
===========================================
Files 744 744
Lines 49081 49125 +44
Branches 7797 7816 +19
===========================================
+ Hits 29703 29704 +1
- Misses 17978 18019 +41
- Partials 1400 1402 +2 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
Caideyipi
left a comment
There was a problem hiding this comment.
I reviewed the range semantics and ran the new API against the current IoTDB byte-scanning helper on Windows/JDK 17, using 64 rotating bitmaps and current-thread CPU/allocation metrics.
Correctness looks good: the exhaustive range test passes locally (18/18 BitMapTest methods), overflow-safe range validation is sound, and the public empty-range semantics are clear.
There is one performance concern with sharing the extractBits implementation across both bitmap representations. Representative results for isRangeAnyMarked on 64-bit ranges were:
| representation / range | current IoTDB helper | new API |
|---|---|---|
| array-backed prefix | 4.688 ns, 0 B | 7.813 ns, 0 B |
| array-backed partial | 4.688 ns, 0 B | 7.813 ns, 0 B |
| array-backed next block | 3.125 ns, 0 B | 7.813 ns, 0 B |
| long-backed prefix | 3.125 ns, 0 B | 1.563 ns, 0 B |
| long-backed partial | 10.938 ns, 32 B | 3.125 ns, 0 B |
So the API is a clear win for the long-backed implementation, especially because it eliminates getByteArray() allocation for non-prefix ranges, but the generic extractBits path is about 1.7-2.5x slower for array-backed bitmaps. The latter matters for IoTDB tablets larger than 64 rows, where 64-row block checks commonly operate on an array-backed input bitmap.
Could we keep the public API/range validation here, but provide representation-specific fast paths?
BitMapLongImpl: shifted value +lowerBitsMask(length)for any/all/none.BitMapArrayImpl: first/last byte masks plus direct scanning of complete middle bytes, avoiding reconstruction of along.- Add a small performance comparison covering long/array-backed bitmaps at
(0, 64),(1, 63), and(64, 64).
It would also be useful to add a true full-64-bit isRangeAllMarked case and an all-marked range crossing a 64-bit boundary; the current patterned oracle is exhaustive over ranges but does not exercise those results as true for a complete batch.
|
Thanks for the detailed analysis. Addressed in 031dead:
I reran:
The Maven configuration runs the selected test twice. Both runs showed:
|
Caideyipi
left a comment
There was a problem hiding this comment.
Re-reviewed the updated implementation at 031dead. The representation-specific fast paths address the previous array-backed regression: local targeted runs showed array-backed performance at parity with the current IoTDB helper, while the long-backed path retained its speedup and eliminated the 32 B/op allocation. BitMapTest passed 18/18, including the added full-64-bit and boundary-crossing cases.
Summary
isRangeAnyMarked(int start, int length)to detect whether a range contains a marked bitisRangeAllMarked(int start, int length)to detect whether every bit in a range is markedisRangeNoneMarked(int start, int length)to detect whether a range contains no marked bitsSemantics
falseforisRangeAnyMarkedtrueforisRangeAllMarkedandisRangeNoneMarkedIndexOutOfBoundsExceptionVerification
mvn -P with-java -pl java/tsfile -am -Dtest=BitMapTest -Dsurefire.failIfNoSpecifiedTests=false test