Skip to content

Commit 5ea0f05

Browse files
authored
Optimize TopGroups.merge() maxScore computation for relevance sorting (#15879)
When docSort is Sort.RELEVANCE, derive each group's maxScore directly from mergedTopDocs.scoreDocs[0] instead of accumulating across shards via nonNANmax. Also hoist docSort.equals(Sort.RELEVANCE) into a local boolean to avoid repeated equals() calls in the per-group and per-shard loops. Signed-off-by: Binlong Gao <gbinlong@amazon.com>
1 parent 1ca7257 commit 5ea0f05

2 files changed

Lines changed: 13 additions & 4 deletions

File tree

lucene/CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ Optimizations
364364

365365
* GITHUB#15779: Improve BytesRefHash.add performance by optimize rehash operation (tyronecai)
366366

367+
* GITHUB#15879: Optimize TopGroups.merge() maxScore computation for relevance sorting (Binlong Gao)
368+
367369
* GITHUB#15896: Skip heavy TreeSet opts for the first group in SearchGroup#merge (Binlong Gao)
368370

369371
* GITHUB#15886: Cache frozen FieldType to skip redundant schema validation. (Tim Brooks)

lucene/grouping/src/java/org/apache/lucene/search/grouping/TopGroups.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ public static <T> TopGroups<T> merge(
156156
final GroupDocs<T>[] mergedGroupDocs = new GroupDocs[numGroups];
157157

158158
final TopDocs[] shardTopDocs;
159-
if (docSort.equals(Sort.RELEVANCE)) {
159+
final boolean sortByRelevance = docSort.equals(Sort.RELEVANCE);
160+
if (sortByRelevance) {
160161
shardTopDocs = new TopDocs[shardGroups.size()];
161162
} else {
162163
shardTopDocs = new TopFieldDocs[shardGroups.size()];
@@ -190,7 +191,7 @@ public static <T> TopGroups<T> merge(
190191
}
191192
*/
192193

193-
if (docSort.equals(Sort.RELEVANCE)) {
194+
if (sortByRelevance) {
194195
shardTopDocs[shardIDX] =
195196
new TopDocs(shardGroupDocs.totalHits(), shardGroupDocs.scoreDocs());
196197
} else {
@@ -203,15 +204,21 @@ public static <T> TopGroups<T> merge(
203204
shardTopDocs[shardIDX].scoreDocs[i].shardIndex = shardIDX;
204205
}
205206

206-
maxScore = nonNANmax(maxScore, shardGroupDocs.maxScore());
207+
if (!sortByRelevance) {
208+
maxScore = nonNANmax(maxScore, shardGroupDocs.maxScore());
209+
}
207210
assert shardGroupDocs.totalHits().relation() == Relation.EQUAL_TO;
208211
totalHits += shardGroupDocs.totalHits().value();
209212
scoreSum += shardGroupDocs.score();
210213
}
211214

212215
final TopDocs mergedTopDocs;
213-
if (docSort.equals(Sort.RELEVANCE)) {
216+
if (sortByRelevance) {
214217
mergedTopDocs = TopDocs.merge(docOffset + docTopN, shardTopDocs);
218+
// When sorting by relevance, the highest-scoring doc is first, so we can
219+
// derive maxScore directly instead of accumulating across shards.
220+
maxScore =
221+
mergedTopDocs.scoreDocs.length == 0 ? Float.NaN : mergedTopDocs.scoreDocs[0].score;
215222
} else {
216223
mergedTopDocs = TopDocs.merge(docSort, docOffset + docTopN, (TopFieldDocs[]) shardTopDocs);
217224
}

0 commit comments

Comments
 (0)