Optimize MaxScoreBulkScorer (#13544)

Don't use Comparator.comparingDouble(...) in a hotish loop here, it
causes allocations that escape analysis is not able to remove.
=> lets just manually inline this to get predictable behavior and save
up to 0.5% of all allocations in some benchmark runs.
This commit is contained in:
Armin Braun 2024-07-08 10:53:26 +02:00 committed by GitHub
parent 2a8d328ab2
commit 675772546c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
1 changed files with 7 additions and 4 deletions

View File

@ -18,7 +18,6 @@ package org.apache.lucene.search;
import java.io.IOException;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import org.apache.lucene.util.Bits;
import org.apache.lucene.util.FixedBitSet;
@ -43,7 +42,7 @@ final class MaxScoreBulkScorer extends BulkScorer {
int firstRequiredScorer;
private final long cost;
float minCompetitiveScore;
private Score scorable = new Score();
private final Score scorable = new Score();
final double[] maxScoreSums;
private final long[] windowMatches = new long[FixedBitSet.bits2words(INNER_WINDOW_SIZE)];
@ -333,10 +332,14 @@ final class MaxScoreBulkScorer extends BulkScorer {
// make a difference when using custom scores (like FuzzyQuery), high query-time boosts, or
// scoring based on wacky weights.
System.arraycopy(allScorers, 0, scratch, 0, allScorers.length);
// Do not use Comparator#comparingDouble below, it might cause unnecessary allocations
Arrays.sort(
scratch,
Comparator.comparingDouble(
scorer -> (double) scorer.maxWindowScore / Math.max(1L, scorer.cost)));
(scorer1, scorer2) -> {
return Double.compare(
(double) scorer1.maxWindowScore / Math.max(1L, scorer1.cost),
(double) scorer2.maxWindowScore / Math.max(1L, scorer2.cost));
});
double maxScoreSum = 0;
firstEssentialScorer = 0;
for (int i = 0; i < allScorers.length; ++i) {