You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by jp...@apache.org on 2025/01/23 13:48:08 UTC
(lucene) branch branch_10x updated: Add small bias towards bit set encoding. (#14155)
This is an automated email from the ASF dual-hosted git repository.
jpountz pushed a commit to branch branch_10x
in repository https://gitbox.apache.org/repos/asf/lucene.git
The following commit(s) were added to refs/heads/branch_10x by this push:
new 4b270750eba Add small bias towards bit set encoding. (#14155)
4b270750eba is described below
commit 4b270750eba2b9cf89f4462123e07a766044f6bb
Author: Adrien Grand <jp...@gmail.com>
AuthorDate: Thu Jan 23 14:40:03 2025 +0100
Add small bias towards bit set encoding. (#14155)
Currently, blocks of postings get encoded as a bit set instead of packed deltas
(FOR) whenever the bit set is more storage-efficient. However, the bit set
approach is quite more CPU-efficient at search time, so this PR introduces a
small bias towards the bit set encoding by using it as soon as it's more
storage-efficient than FOR with the next number of bits per value.
The impact on storage efficiency of the Wikipedia dataset is negligible (+0.15%
on `.doc` files, while `.doc` files don't dominate storage requirements,
positions do) while some queries get a good speedup.
---
.../codecs/lucene101/Lucene101PostingsWriter.java | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene101/Lucene101PostingsWriter.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene101/Lucene101PostingsWriter.java
index 1cabefe681e..3d19a69b82d 100644
--- a/lucene/core/src/java/org/apache/lucene/codecs/lucene101/Lucene101PostingsWriter.java
+++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene101/Lucene101PostingsWriter.java
@@ -424,15 +424,17 @@ public class Lucene101PostingsWriter extends PushPostingsWriterBase {
long numSkipBytes = level0Output.size();
// Now we need to decide whether to encode block deltas as packed integers (FOR) or unary
// codes (bit set). FOR makes #nextDoc() a bit faster while the bit set approach makes
- // #advance() sometimes faster and #intoBitSet() much faster. Since the trade-off is not
- // obvious, we make the decision purely based on storage efficiency, using the approach that
- // requires fewer bits to encode the block.
+ // #advance() usually faster and #intoBitSet() much faster. In the end, we make the decision
+ // based on storage requirements, picking the bit set approach whenever it's more
+ // storage-efficient than the next number of bits per value (which effectively slightly biases
+ // towards the bit set approach).
int bitsPerValue = forDeltaUtil.bitsRequired(docDeltaBuffer);
int sum = Math.toIntExact(Arrays.stream(docDeltaBuffer).sum());
int numBitSetLongs = FixedBitSet.bits2words(sum);
+ int numBitsNextBitsPerValue = Math.min(Integer.SIZE, bitsPerValue + 1) * BLOCK_SIZE;
if (sum == BLOCK_SIZE) {
level0Output.writeByte((byte) 0);
- } else if (version < VERSION_DENSE_BLOCKS_AS_BITSETS || bitsPerValue * BLOCK_SIZE < sum) {
+ } else if (version < VERSION_DENSE_BLOCKS_AS_BITSETS || numBitsNextBitsPerValue <= sum) {
level0Output.writeByte((byte) bitsPerValue);
forDeltaUtil.encodeDeltas(bitsPerValue, docDeltaBuffer, level0Output);
} else {
@@ -444,10 +446,9 @@ public class Lucene101PostingsWriter extends PushPostingsWriterBase {
s += i;
spareBitSet.set(s);
}
- // Since we use the bit set encoding when it's more storage efficient than storing deltas,
- // we know that each doc ID uses less than 32 bits, the maximum number of bits required to
- // store a delta between consecutive doc IDs. So in the end, the bit set cannot have more
- // than BLOCK_SIZE * Integer.SIZE / Long.SIZE = 64 longs, which fits on a byte.
+ // We never use the bit set encoding when it requires more than Integer.SIZE=32 bits per
+ // value. So the bit set cannot have more than BLOCK_SIZE * Integer.SIZE / Long.SIZE = 64
+ // longs, which fits on a byte.
assert numBitSetLongs <= BLOCK_SIZE / 2;
level0Output.writeByte((byte) -numBitSetLongs);
for (int i = 0; i < numBitSetLongs; ++i) {