Skip to content

Commit

Permalink
Make inlining of FixedBitSet#get more predictable when checking live …
Browse files Browse the repository at this point in the history
…docs. (#14077)

This helps make calls sites of `Bits#get` bimorphic at most when checking live
docs. This helps because calls to `FixedBitSet#get` can then be inlined when
live docs are stored in a `FixedBitSet`. Another reason why this is important
is because these calls could be subject to auto-vectorizing when applied to an
array of doc IDs, which cannot apply if the `FixedBitSet#get` call is not
inlined.

While live docs are stored in a `FixedBitSet` by default, some features like
document-level security sometimes create wrappers.
  • Loading branch information
jpountz authored Dec 23, 2024
1 parent 42c4c11 commit b0585f1
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -845,7 +845,9 @@ protected void searchLeaf(
scorer = new TimeLimitingBulkScorer(scorer, queryTimeout);
}
try {
scorer.score(leafCollector, ctx.reader().getLiveDocs(), minDocId, maxDocId);
// Optimize for the case when live docs are stored in a FixedBitSet.
Bits acceptDocs = ScorerUtil.likelyFixedBitSet(ctx.reader().getLiveDocs());
scorer.score(leafCollector, acceptDocs, minDocId, maxDocId);
} catch (
@SuppressWarnings("unused")
CollectionTerminatedException e) {
Expand Down
38 changes: 38 additions & 0 deletions lucene/core/src/java/org/apache/lucene/search/ScorerUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import org.apache.lucene.index.TermsEnum;
import org.apache.lucene.store.ByteBuffersDirectory;
import org.apache.lucene.store.Directory;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.FixedBitSet;
import org.apache.lucene.util.PriorityQueue;

/** Util class for Scorer related methods */
Expand Down Expand Up @@ -108,4 +110,40 @@ static Scorable likelyTermScorer(Scorable scorable) {
}
return scorable;
}

/**
* Optimize {@link Bits} representing the set of accepted documents for the case when it is likely
* implemented via a {@link FixedBitSet}. This helps make calls to {@link Bits#get(int)}
* inlinable, which in-turn helps speed up query evaluation. This is especially helpful as
* inlining will sometimes enable auto-vectorizing shifts and masks that are done in {@link
* FixedBitSet#get(int)}.
*/
static Bits likelyFixedBitSet(Bits acceptDocs) {
if (acceptDocs instanceof FixedBitSet) {
return acceptDocs;
} else if (acceptDocs != null) {
return new FilterBits(acceptDocs);
} else {
return null;
}
}

private static class FilterBits implements Bits {

private final Bits in;

FilterBits(Bits in) {
this.in = in;
}

@Override
public boolean get(int index) {
return in.get(index);
}

@Override
public int length() {
return in.length();
}
}
}

0 comments on commit b0585f1

Please sign in to comment.