diff --git a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90DocValuesProducer.java b/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90DocValuesProducer.java index 2a99bd59b922..f14bd16396ac 100644 --- a/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90DocValuesProducer.java +++ b/lucene/core/src/java/org/apache/lucene/codecs/lucene90/Lucene90DocValuesProducer.java @@ -21,6 +21,7 @@ import static org.apache.lucene.codecs.lucene90.Lucene90DocValuesFormat.TERMS_DICT_BLOCK_LZ4_SHIFT; import java.io.IOException; +import java.util.Arrays; import org.apache.lucene.codecs.CodecUtil; import org.apache.lucene.codecs.DocValuesProducer; import org.apache.lucene.index.BaseTermsEnum; @@ -432,6 +433,7 @@ private abstract static class DenseNumericDocValues extends NumericDocValues { final int maxDoc; int doc = -1; + LongValues bulkValues; DenseNumericDocValues(int maxDoc) { this.maxDoc = maxDoc; @@ -470,6 +472,33 @@ public long cost() { public int docIDRunEnd() throws IOException { return maxDoc; } + + final boolean isDense(int size, int[] docs, int bpv) { + if (size < 2) { + return false; + } + // number of longs in the range of docs + final long longsInRange = (long) (docs[size - 1] - docs[0]) * bpv / 64; + + // if every long value will be read, then it is dense (assuming uniform distribution) + if (size < longsInRange) { + return false; + } + return true; + } + + /** only call this method when {@link #isDense(int, int[], int)} returned {@code true}. */ + void readLongValuesFromBulkInstance( + int size, int[] docs, long[] longValues, RandomAccessInput slice, NumericEntry entry) { + if (bulkValues == null) { + bulkValues = DirectReader.getMergeInstance(slice, entry.bitsPerValue, 0, entry.numValues); + } + + for (int i = 0; i < size; ++i) { + longValues[i] = bulkValues.get(docs[i]); + } + advanceExact(docs[size - 1]); + } } private abstract static class SparseNumericDocValues extends NumericDocValues { @@ -537,6 +566,15 @@ private NumericDocValues getNumeric(NumericEntry entry) throws IOException { public long longValue() throws IOException { return entry.minValue; } + + @Override + public void longValues(int size, int[] docs, long[] values, long defaultValue) { + if (size == 0) { + return; + } + Arrays.fill(values, 0, size, entry.minValue); + advanceExact(docs[size - 1]); + } }; } else { final RandomAccessInput slice = @@ -555,6 +593,8 @@ public long longValue() throws IOException { public long longValue() throws IOException { return vBPVReader.getLongValue(doc); } + + // todo: override longValues method to use merge instance for vBPVReader? }; } else { final LongValues values = @@ -566,6 +606,19 @@ public long longValue() throws IOException { public long longValue() throws IOException { return table[(int) values.get(doc)]; } + + @Override + public void longValues(int size, int[] docs, long[] longValues, long defaultValue) + throws IOException { + if (isDense(size, docs, entry.bitsPerValue)) { + readLongValuesFromBulkInstance(size, docs, longValues, slice, entry); + for (int i = 0; i < size; ++i) { + longValues[i] = table[(int) longValues[i]]; + } + } else { + super.longValues(size, docs, longValues, defaultValue); + } + } }; } else if (entry.gcd == 1 && entry.minValue == 0) { // Common case for ordinals, which are encoded as numerics @@ -574,6 +627,16 @@ public long longValue() throws IOException { public long longValue() throws IOException { return values.get(doc); } + + @Override + public void longValues(int size, int[] docs, long[] longValues, long defaultValue) + throws IOException { + if (isDense(size, docs, entry.bitsPerValue)) { + readLongValuesFromBulkInstance(size, docs, longValues, slice, entry); + } else { + super.longValues(size, docs, longValues, defaultValue); + } + } }; } else { final long mul = entry.gcd; @@ -583,6 +646,19 @@ public long longValue() throws IOException { public long longValue() throws IOException { return mul * values.get(doc) + delta; } + + @Override + public void longValues(int size, int[] docs, long[] longValues, long defaultValue) + throws IOException { + if (isDense(size, docs, entry.bitsPerValue)) { + readLongValuesFromBulkInstance(size, docs, longValues, slice, entry); + for (int i = 0; i < size; ++i) { + longValues[i] = mul * longValues[i] + delta; + } + } else { + super.longValues(size, docs, longValues, defaultValue); + } + } }; } }