diff --git a/lucene/CHANGES.txt b/lucene/CHANGES.txt index e90ca7c9edb0..3b0f76fb1006 100644 --- a/lucene/CHANGES.txt +++ b/lucene/CHANGES.txt @@ -258,6 +258,8 @@ Optimizations * GITHUB#15083: Use DocValuesSkippers in SortedNumericDocValuesRangeQuery#rewrite(). (Alan Woodward) +* GITHUB#15081: Filter by maxOtherDoc first to reduce the overhead of filterCompetitiveHits. (Ge Song) + Changes in Runtime Behavior --------------------- * GITHUB#14823: Decrease TieredMergePolicy's default number of segments per diff --git a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java index 21f8af990b85..2a66428dd247 100644 --- a/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/BlockMaxConjunctionBulkScorer.java @@ -172,11 +172,12 @@ private void scoreWindowScoreFirst( return; } + int maxOtherDoc = -1; for (scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer); docAndScoreBuffer.size > 0; scorers[0].nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer); + docAndScoreAccBuffer.copyWithMinDocRequired(docAndScoreBuffer, maxOtherDoc); for (int i = 1; i < scorers.length; ++i) { double sumOfOtherClause = sumOfOtherClauses[i]; @@ -188,6 +189,7 @@ private void scoreWindowScoreFirst( } ScorerUtil.applyRequiredClause(docAndScoreAccBuffer, iterators[i], scorables[i]); + maxOtherDoc = Math.max(iterators[i].docID(), maxOtherDoc); } for (int i = 0; i < docAndScoreAccBuffer.size; ++i) { @@ -196,10 +198,6 @@ private void scoreWindowScoreFirst( } } - int maxOtherDoc = -1; - for (int i = 1; i < iterators.length; ++i) { - maxOtherDoc = Math.max(iterators[i].docID(), maxOtherDoc); - } if (lead.docID() < maxOtherDoc) { lead.advance(maxOtherDoc); } diff --git a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java index ed5ffbc3f9a3..36fe7e12c990 100644 --- a/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java +++ b/lucene/core/src/java/org/apache/lucene/search/DocAndScoreAccBuffer.java @@ -74,4 +74,18 @@ public void copyFrom(DocAndFloatFeatureBuffer buffer) { } this.size = buffer.size; } + + public void copyWithMinDocRequired(DocAndFloatFeatureBuffer buffer, int minDocInclusive) { + int i = 0; + for (; i < buffer.size && buffer.docs[i] < minDocInclusive; ++i) { + // skip entries with doc IDs below the minimum + } + int newSize = buffer.size - i; + growNoCopy(newSize); + System.arraycopy(buffer.docs, i, docs, 0, newSize); + for (int j = i; j < buffer.size; ++j) { + scores[j - i] = buffer.features[j]; + } + this.size = newSize; + } } diff --git a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java index c723cbe00f13..2de1513b70c6 100644 --- a/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java +++ b/lucene/core/src/java/org/apache/lucene/search/MaxScoreBulkScorer.java @@ -246,11 +246,12 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD assert essentialQueue.size() == 1; assert lead1 == essentialQueue.top(); + int maxOtherDoc = -1; for (lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer); docAndScoreBuffer.size > 0; lead1.scorer.nextDocsAndScores(max, acceptDocs, docAndScoreBuffer)) { - docAndScoreAccBuffer.copyFrom(docAndScoreBuffer); + docAndScoreAccBuffer.copyWithMinDocRequired(docAndScoreBuffer, maxOtherDoc); for (int i = allScorers.length - 2; i >= firstRequiredScorer; --i) { @@ -264,6 +265,7 @@ private void scoreInnerWindowAsConjunction(LeafCollector collector, Bits acceptD DisiWrapper scorer = allScorers[i]; ScorerUtil.applyRequiredClause(docAndScoreAccBuffer, scorer.iterator, scorer.scorable); + maxOtherDoc = Math.max(maxOtherDoc, scorer.iterator.docID()); } scoreNonEssentialClauses(collector, docAndScoreAccBuffer, firstRequiredScorer);