Skip to content

Commit f1e151e

Browse files
authored
Implement longValues for MultiFieldNormValues to speedup CombinedQuery (#15261)
1 parent a8888ca commit f1e151e

File tree

2 files changed

+37
-2
lines changed

2 files changed

+37
-2
lines changed

lucene/CHANGES.txt

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

190190
* GITHUB#14863: Perform scoring for 4, 7, 8 bit quantized vectors off-heap. (Kaival Parikh)
191191

192+
* GITHUB#15261: Implement longValues for MultiFieldNormValues to speedup CombinedQuery (Ge Song)
193+
192194
Bug Fixes
193195
---------------------
194196
* GITHUB#14161: PointInSetQuery's constructor now throws IllegalArgumentException

lucene/core/src/java/org/apache/lucene/search/MultiNormsLeafSimScorer.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@
1818

1919
import java.io.IOException;
2020
import java.util.ArrayList;
21+
import java.util.Arrays;
2122
import java.util.Collection;
2223
import java.util.HashSet;
2324
import java.util.List;
2425
import java.util.Objects;
2526
import java.util.Set;
2627
import org.apache.lucene.index.LeafReader;
2728
import org.apache.lucene.index.NumericDocValues;
29+
import org.apache.lucene.internal.hppc.FloatArrayList;
2830
import org.apache.lucene.search.CombinedFieldQuery.FieldAndWeight;
2931
import org.apache.lucene.search.similarities.Similarity.BulkSimScorer;
3032
import org.apache.lucene.search.similarities.Similarity.SimScorer;
@@ -127,8 +129,10 @@ public float score(int doc, float freq) throws IOException {
127129
*/
128130
public void scoreRange(DocAndFloatFeatureBuffer buffer) throws IOException {
129131
normValues = ArrayUtil.growNoCopy(normValues, buffer.size);
130-
for (int i = 0; i < buffer.size; i++) {
131-
normValues[i] = getNormValue(buffer.docs[i]);
132+
if (norms != null) {
133+
norms.longValues(buffer.size, buffer.docs, normValues, 1L);
134+
} else {
135+
Arrays.fill(normValues, 0, buffer.size, 1L);
132136
}
133137
bulkScorer.score(buffer.size, buffer.features, normValues, buffer.features);
134138
}
@@ -145,6 +149,7 @@ public Explanation explain(int doc, Explanation freqExpl) throws IOException {
145149

146150
private static class MultiFieldNormValues extends NumericDocValues {
147151
private final NumericDocValues[] normsArr;
152+
private float[] accBuf = FloatArrayList.EMPTY_ARRAY;
148153
private final float[] weightArr;
149154
private long current;
150155
private int docID = -1;
@@ -193,5 +198,33 @@ public int advance(int target) {
193198
public long cost() {
194199
throw new UnsupportedOperationException();
195200
}
201+
202+
@Override
203+
public void longValues(int size, int[] docs, long[] values, long defaultValue)
204+
throws IOException {
205+
if (accBuf.length < size) {
206+
accBuf = new float[ArrayUtil.oversize(size, Float.BYTES)];
207+
} else {
208+
Arrays.fill(accBuf, 0f);
209+
}
210+
211+
for (int i = 0; i < normsArr.length; i++) {
212+
// this code relies on the assumption that document length can never be equal to 0,
213+
// so we can use 0L to indicate whether we have a norm value or not
214+
normsArr[i].longValues(size, docs, values, 0L);
215+
float weight = weightArr[i];
216+
for (int j = 0; j < size; j++) {
217+
accBuf[j] += weight * LENGTH_TABLE[Byte.toUnsignedInt((byte) values[j])];
218+
}
219+
}
220+
221+
for (int i = 0; i < size; i++) {
222+
if (accBuf[i] == 0f) {
223+
values[i] = defaultValue;
224+
} else {
225+
values[i] = SmallFloat.intToByte4(Math.round(accBuf[i]));
226+
}
227+
}
228+
}
196229
}
197230
}

0 commit comments

Comments
 (0)