diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumer.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumer.java index c75fd6a470add..f93078da8f175 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumer.java +++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumer.java @@ -73,6 +73,8 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer { private final int minDocsPerOrdinalForOrdinalRangeEncoding; final boolean enableOptimizedMerge; private final int primarySortFieldNumber; + private final int numericBlockShift; + private final int numericBlockSize; final SegmentWriteState state; final BinaryDVCompressionMode binaryDVCompressionMode; private final boolean enablePerBlockCompression; // only false for testing @@ -84,6 +86,7 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer { int skipIndexIntervalSize, int minDocsPerOrdinalForOrdinalRangeEncoding, boolean enableOptimizedMerge, + int numericBlockShift, String dataCodec, String dataExtension, String metaCodec, @@ -97,6 +100,9 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer { this.minDocsPerOrdinalForOrdinalRangeEncoding = minDocsPerOrdinalForOrdinalRangeEncoding; this.primarySortFieldNumber = ES819TSDBDocValuesProducer.primarySortFieldNumber(state.segmentInfo, state.fieldInfos); this.context = state.context; + this.numericBlockShift = numericBlockShift; + this.numericBlockSize = 1 << numericBlockShift; + boolean success = false; try { final String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension); @@ -108,6 +114,7 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer { state.segmentInfo.getId(), state.segmentSuffix ); + String metaName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, metaExtension); meta = state.directory.createOutput(metaName, state.context); CodecUtil.writeIndexHeader( @@ -117,6 +124,8 @@ final class ES819TSDBDocValuesConsumer extends XDocValuesConsumer { state.segmentInfo.getId(), state.segmentSuffix ); + meta.writeByte((byte) numericBlockShift); + maxDoc = state.segmentInfo.maxDoc(); this.skipIndexIntervalSize = skipIndexIntervalSize; this.enableOptimizedMerge = enableOptimizedMerge; @@ -218,13 +227,13 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer, indexWriter = DirectMonotonicWriter.getInstance( meta, new ByteBuffersIndexOutput(indexOut, "temp-dv-index", "temp-dv-index"), - 1L + ((numValues - 1) >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT), + 1L + ((numValues - 1) >>> numericBlockShift), ES819TSDBDocValuesFormat.DIRECT_MONOTONIC_BLOCK_SHIFT ); meta.writeInt(DIRECT_MONOTONIC_BLOCK_SHIFT); - final long[] buffer = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; + final long[] buffer = new long[numericBlockSize]; int bufferSize = 0; - final TSDBDocValuesEncoder encoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); + final TSDBDocValuesEncoder encoder = new TSDBDocValuesEncoder(numericBlockSize); values = valuesProducer.getSortedNumeric(field); final int bitsPerOrd = maxOrd >= 0 ? PackedInts.bitsRequired(maxOrd - 1) : -1; if (valuesProducer.mergeStats.supported() && numDocsWithValue < maxDoc) { @@ -240,7 +249,7 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer, } for (int i = 0; i < count; ++i) { buffer[bufferSize++] = values.nextValue(); - if (bufferSize == ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE) { + if (bufferSize == numericBlockSize) { indexWriter.add(data.getFilePointer() - valuesDataOffset); if (maxOrd >= 0) { encoder.encodeOrdinals(buffer, data, bitsPerOrd); @@ -254,7 +263,7 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer, if (bufferSize > 0) { indexWriter.add(data.getFilePointer() - valuesDataOffset); // Fill unused slots in the block with zeroes rather than junk - Arrays.fill(buffer, bufferSize, ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE, 0L); + Arrays.fill(buffer, bufferSize, numericBlockSize, 0L); if (maxOrd >= 0) { encoder.encodeOrdinals(buffer, data, bitsPerOrd); } else { diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormat.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormat.java index b479ff2a475d8..833e5c551efd3 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormat.java +++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormat.java @@ -37,8 +37,7 @@ public class ES819TSDBDocValuesFormat extends org.apache.lucene.codecs.DocValuesFormat { static final int NUMERIC_BLOCK_SHIFT = 7; - public static final int NUMERIC_BLOCK_SIZE = 1 << NUMERIC_BLOCK_SHIFT; - static final int NUMERIC_BLOCK_MASK = NUMERIC_BLOCK_SIZE - 1; + static final int NUMERIC_LARGE_BLOCK_SHIFT = 9; static final int DIRECT_MONOTONIC_BLOCK_SHIFT = 16; static final String CODEC_NAME = "ES819TSDB"; static final String DATA_CODEC = "ES819TSDBDocValuesData"; @@ -53,7 +52,8 @@ public class ES819TSDBDocValuesFormat extends org.apache.lucene.codecs.DocValues static final int VERSION_START = 0; static final int VERSION_BINARY_DV_COMPRESSION = 1; - static final int VERSION_CURRENT = VERSION_BINARY_DV_COMPRESSION; + static final int VERSION_NUMERIC_LARGE_BLOCKS = 2; + static final int VERSION_CURRENT = VERSION_NUMERIC_LARGE_BLOCKS; static final int TERMS_DICT_BLOCK_LZ4_SHIFT = 6; static final int TERMS_DICT_BLOCK_LZ4_SIZE = 1 << TERMS_DICT_BLOCK_LZ4_SHIFT; @@ -130,14 +130,18 @@ private static boolean getOptimizedMergeEnabledDefault() { */ public static final int ORDINAL_RANGE_ENCODING_BLOCK_SHIFT = 12; + final int numericBlockShift; final int skipIndexIntervalSize; final int minDocsPerOrdinalForRangeEncoding; final boolean enableOptimizedMerge; final BinaryDVCompressionMode binaryDVCompressionMode; final boolean enablePerBlockCompression; - /** Default constructor. */ public ES819TSDBDocValuesFormat() { + this(NUMERIC_BLOCK_SHIFT); + } + + public ES819TSDBDocValuesFormat(int numericBlockShift) { this( DEFAULT_SKIP_INDEX_INTERVAL_SIZE, ORDINAL_RANGE_ENCODING_MIN_DOC_PER_ORDINAL, @@ -153,7 +157,8 @@ public ES819TSDBDocValuesFormat(BinaryDVCompressionMode binaryDVCompressionMode) ORDINAL_RANGE_ENCODING_MIN_DOC_PER_ORDINAL, OPTIMIZED_MERGE_ENABLE_DEFAULT, binaryDVCompressionMode, - true + true, + NUMERIC_BLOCK_SHIFT ); } @@ -163,7 +168,8 @@ public ES819TSDBDocValuesFormat(BinaryDVCompressionMode binaryDVCompressionMode, ORDINAL_RANGE_ENCODING_MIN_DOC_PER_ORDINAL, OPTIMIZED_MERGE_ENABLE_DEFAULT, binaryDVCompressionMode, - enablePerBlockCompression + enablePerBlockCompression, + NUMERIC_BLOCK_SHIFT ); } @@ -174,8 +180,27 @@ public ES819TSDBDocValuesFormat( boolean enableOptimizedMerge, BinaryDVCompressionMode binaryDVCompressionMode, final boolean enablePerBlockCompression + ) { + this( + skipIndexIntervalSize, + minDocsPerOrdinalForRangeEncoding, + enableOptimizedMerge, + binaryDVCompressionMode, + enablePerBlockCompression, + NUMERIC_BLOCK_SHIFT + ); + } + + public ES819TSDBDocValuesFormat( + int skipIndexIntervalSize, + int minDocsPerOrdinalForRangeEncoding, + boolean enableOptimizedMerge, + BinaryDVCompressionMode binaryDVCompressionMode, + final boolean enablePerBlockCompression, + final int numericBlockShift ) { super(CODEC_NAME); + assert numericBlockShift == NUMERIC_BLOCK_SHIFT || numericBlockShift == NUMERIC_LARGE_BLOCK_SHIFT : numericBlockShift; if (skipIndexIntervalSize < 2) { throw new IllegalArgumentException("skipIndexIntervalSize must be > 1, got [" + skipIndexIntervalSize + "]"); } @@ -184,6 +209,7 @@ public ES819TSDBDocValuesFormat( this.enableOptimizedMerge = enableOptimizedMerge; this.binaryDVCompressionMode = binaryDVCompressionMode; this.enablePerBlockCompression = enablePerBlockCompression; + this.numericBlockShift = numericBlockShift; } @Override @@ -195,6 +221,7 @@ public DocValuesConsumer fieldsConsumer(SegmentWriteState state) throws IOExcept skipIndexIntervalSize, minDocsPerOrdinalForRangeEncoding, enableOptimizedMerge, + numericBlockShift, DATA_CODEC, DATA_EXTENSION, META_CODEC, diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesProducer.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesProducer.java index 74b98f6cdfca8..6c5b290880003 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesProducer.java +++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesProducer.java @@ -71,6 +71,9 @@ final class ES819TSDBDocValuesProducer extends DocValuesProducer { private final int maxDoc; final int version; private final boolean merging; + private final int numericBlockShift; + private final int numericBlockSize; + private final int numericBlockMask; ES819TSDBDocValuesProducer(SegmentReadState state, String dataCodec, String dataExtension, String metaCodec, String metaExtension) throws IOException { @@ -86,6 +89,7 @@ final class ES819TSDBDocValuesProducer extends DocValuesProducer { // read in the entries from the metadata file. int version = -1; + int blockShift = ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; String metaName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, metaExtension); try (ChecksumIndexInput in = state.directory.openChecksumInput(metaName)) { @@ -100,9 +104,10 @@ final class ES819TSDBDocValuesProducer extends DocValuesProducer { state.segmentInfo.getId(), state.segmentSuffix ); - - readFields(in, state.fieldInfos, version); - + if (version >= ES819TSDBDocValuesFormat.VERSION_NUMERIC_LARGE_BLOCKS) { + blockShift = in.readByte(); + } + readFields(in, state.fieldInfos, version, blockShift); } catch (Throwable exception) { priorE = exception; } finally { @@ -110,6 +115,10 @@ final class ES819TSDBDocValuesProducer extends DocValuesProducer { } } + this.numericBlockShift = blockShift; + this.numericBlockSize = 1 << blockShift; + this.numericBlockMask = numericBlockSize - 1; + String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension); this.data = state.directory.openInput(dataName, state.context); boolean success = false; @@ -152,7 +161,8 @@ private ES819TSDBDocValuesProducer( int maxDoc, int version, int primarySortFieldNumber, - boolean merging + boolean merging, + int numericBlockShift ) { this.numerics = numerics; this.binaries = binaries; @@ -165,6 +175,9 @@ private ES819TSDBDocValuesProducer( this.version = version; this.primarySortFieldNumber = primarySortFieldNumber; this.merging = merging; + this.numericBlockShift = numericBlockShift; + this.numericBlockSize = 1 << numericBlockShift; + this.numericBlockMask = numericBlockSize - 1; } @Override @@ -180,7 +193,8 @@ public DocValuesProducer getMergeInstance() { maxDoc, version, primarySortFieldNumber, - true + true, + numericBlockShift ); } @@ -819,7 +833,7 @@ public BlockLoader.Block tryRead( } // Falling back to tryRead(...) is safe here, given that current block index wasn't altered by looking ahead. try (var builder = factory.singletonOrdinalsBuilder(this, docs.count() - offset, true)) { - BlockLoader.SingletonLongBuilder delegate = new SingletonLongToSingletonOrdinalDelegate(builder); + BlockLoader.SingletonLongBuilder delegate = new SingletonLongToSingletonOrdinalDelegate(builder, numericBlockSize); var result = denseOrds.tryRead(delegate, docs, offset); if (result != null) { return result; @@ -1516,7 +1530,7 @@ static int primarySortFieldNumber(SegmentInfo segmentInfo, FieldInfos fieldInfos return -1; } - private void readFields(IndexInput meta, FieldInfos infos, int version) throws IOException { + private void readFields(IndexInput meta, FieldInfos infos, int version, int numericBlockShift) throws IOException { for (int fieldNumber = meta.readInt(); fieldNumber != -1; fieldNumber = meta.readInt()) { FieldInfo info = infos.fieldInfo(fieldNumber); if (info == null) { @@ -1527,24 +1541,24 @@ private void readFields(IndexInput meta, FieldInfos infos, int version) throws I skippers.put(info.number, readDocValueSkipperMeta(meta)); } if (type == ES819TSDBDocValuesFormat.NUMERIC) { - numerics.put(info.number, readNumeric(meta)); + numerics.put(info.number, readNumeric(meta, numericBlockShift)); } else if (type == ES819TSDBDocValuesFormat.BINARY) { binaries.put(info.number, readBinary(meta, version)); } else if (type == ES819TSDBDocValuesFormat.SORTED) { - sorted.put(info.number, readSorted(meta)); + sorted.put(info.number, readSorted(meta, numericBlockShift)); } else if (type == ES819TSDBDocValuesFormat.SORTED_SET) { - sortedSets.put(info.number, readSortedSet(meta)); + sortedSets.put(info.number, readSortedSet(meta, numericBlockShift)); } else if (type == ES819TSDBDocValuesFormat.SORTED_NUMERIC) { - sortedNumerics.put(info.number, readSortedNumeric(meta)); + sortedNumerics.put(info.number, readSortedNumeric(meta, numericBlockShift)); } else { throw new CorruptIndexException("invalid type: " + type, meta); } } } - private static NumericEntry readNumeric(IndexInput meta) throws IOException { + private static NumericEntry readNumeric(IndexInput meta, int numericBlockShift) throws IOException { NumericEntry entry = new NumericEntry(); - readNumeric(meta, entry); + readNumeric(meta, entry, numericBlockShift); return entry; } @@ -1559,7 +1573,7 @@ private static DocValuesSkipperEntry readDocValueSkipperMeta(IndexInput meta) th return new DocValuesSkipperEntry(offset, length, minValue, maxValue, docCount, maxDocID); } - private static void readNumeric(IndexInput meta, NumericEntry entry) throws IOException { + private static void readNumeric(IndexInput meta, NumericEntry entry, int numericBlockShift) throws IOException { entry.numValues = meta.readLong(); // Change compared to ES87TSDBDocValuesProducer: entry.numDocsWithField = meta.readInt(); @@ -1573,11 +1587,7 @@ private static void readNumeric(IndexInput meta, NumericEntry entry) throws IOEx final int blockShift = meta.readByte(); entry.sortedOrdinals = DirectMonotonicReader.loadMeta(meta, numOrds + 1, blockShift); } else { - entry.indexMeta = DirectMonotonicReader.loadMeta( - meta, - 1 + ((entry.numValues - 1) >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT), - indexBlockShift - ); + entry.indexMeta = DirectMonotonicReader.loadMeta(meta, 1 + ((entry.numValues - 1) >>> numericBlockShift), indexBlockShift); } entry.indexOffset = meta.readLong(); entry.indexLength = meta.readLong(); @@ -1641,14 +1651,15 @@ private BinaryEntry readBinary(IndexInput meta, int version) throws IOException return entry; } - private static SortedNumericEntry readSortedNumeric(IndexInput meta) throws IOException { + private static SortedNumericEntry readSortedNumeric(IndexInput meta, int numericBlockShift) throws IOException { SortedNumericEntry entry = new SortedNumericEntry(); - readSortedNumeric(meta, entry); + readSortedNumeric(meta, entry, numericBlockShift); return entry; } - private static SortedNumericEntry readSortedNumeric(IndexInput meta, SortedNumericEntry entry) throws IOException { - readNumeric(meta, entry); + private static SortedNumericEntry readSortedNumeric(IndexInput meta, SortedNumericEntry entry, int numericBlockShift) + throws IOException { + readNumeric(meta, entry, numericBlockShift); // We don't read numDocsWithField here any more. if (entry.numDocsWithField != entry.numValues) { entry.addressesOffset = meta.readLong(); @@ -1659,21 +1670,21 @@ private static SortedNumericEntry readSortedNumeric(IndexInput meta, SortedNumer return entry; } - private SortedEntry readSorted(IndexInput meta) throws IOException { + private static SortedEntry readSorted(IndexInput meta, int numericBlockShift) throws IOException { SortedEntry entry = new SortedEntry(); entry.ordsEntry = new NumericEntry(); - readNumeric(meta, entry.ordsEntry); + readNumeric(meta, entry.ordsEntry, numericBlockShift); entry.termsDictEntry = new TermsDictEntry(); readTermDict(meta, entry.termsDictEntry); return entry; } - private SortedSetEntry readSortedSet(IndexInput meta) throws IOException { + private static SortedSetEntry readSortedSet(IndexInput meta, int numericBlockShift) throws IOException { SortedSetEntry entry = new SortedSetEntry(); byte multiValued = meta.readByte(); switch (multiValued) { case 0: // singlevalued - entry.singleValueEntry = readSorted(meta); + entry.singleValueEntry = readSorted(meta, numericBlockShift); return entry; case 1: // multivalued break; @@ -1681,7 +1692,7 @@ private SortedSetEntry readSortedSet(IndexInput meta) throws IOException { throw new CorruptIndexException("Invalid multiValued flag: " + multiValued, meta); } entry.ordsEntry = new SortedNumericEntry(); - readSortedNumeric(meta, entry.ordsEntry); + readSortedNumeric(meta, entry.ordsEntry, numericBlockShift); entry.termsDictEntry = new TermsDictEntry(); readTermDict(meta, entry.termsDictEntry); return entry; @@ -1823,9 +1834,9 @@ public int docIDRunEnd() throws IOException { if (entry.docsWithFieldOffset == -1) { // dense return new BaseDenseNumericValues(maxDoc) { - private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); + private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(numericBlockSize); private long currentBlockIndex = -1; - private final long[] currentBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; + private final long[] currentBlock = new long[numericBlockSize]; // lookahead block private long lookaheadBlockIndex = -1; private long[] lookaheadBlock; @@ -1839,8 +1850,8 @@ public int docIDRunEnd() { @Override public long longValue() throws IOException { final int index = doc; - final int blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; - final int blockInIndex = index & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; + final int blockIndex = index >>> numericBlockShift; + final int blockInIndex = index & numericBlockMask; if (blockIndex == currentBlockIndex) { return currentBlock[blockInIndex]; } @@ -1881,8 +1892,8 @@ BlockLoader.Block tryRead(BlockLoader.SingletonLongBuilder builder, BlockLoader. doc = docs.get(docsCount - 1); for (int i = offset; i < docsCount;) { int index = docs.get(i); - final int blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; - final int blockInIndex = index & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; + final int blockIndex = index >>> numericBlockShift; + final int blockInIndex = index & numericBlockMask; if (blockIndex != currentBlockIndex) { assert blockIndex > currentBlockIndex : blockIndex + " < " + currentBlockIndex; // no need to seek if the loading block is the next block @@ -1901,7 +1912,7 @@ BlockLoader.Block tryRead(BlockLoader.SingletonLongBuilder builder, BlockLoader. // Instead of iterating over docs and find the max length, take an optimistic approach to avoid as // many comparisons as there are remaining docs and instead do at most 7 comparisons: int length = 1; - int remainingBlockLength = Math.min(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE - blockInIndex, docsCount - i); + int remainingBlockLength = Math.min(numericBlockSize - blockInIndex, docsCount - i); for (int newLength = remainingBlockLength; newLength > 1; newLength = newLength >> 1) { int lastIndex = i + newLength - 1; if (isDense(index, docs.get(lastIndex), newLength)) { @@ -1917,15 +1928,15 @@ BlockLoader.Block tryRead(BlockLoader.SingletonLongBuilder builder, BlockLoader. @Override long lookAheadValueAt(int targetDoc) throws IOException { - final int blockIndex = targetDoc >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; - final int valueIndex = targetDoc & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; + final int blockIndex = targetDoc >>> numericBlockShift; + final int valueIndex = targetDoc & numericBlockMask; if (blockIndex == currentBlockIndex) { return currentBlock[valueIndex]; } // load data to the lookahead block if (lookaheadBlockIndex != blockIndex) { if (lookaheadBlock == null) { - lookaheadBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; + lookaheadBlock = new long[numericBlockSize]; lookaheadData = data.slice("look_ahead_values", entry.valuesOffset, entry.valuesLength); } if (lookaheadBlockIndex + 1 != blockIndex) { @@ -1956,10 +1967,10 @@ SortedOrdinalReader sortedOrdinalReader() { entry.numValues ); return new BaseSparseNumericValues(disi) { - private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); + private final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(numericBlockSize); private IndexedDISI lookAheadDISI; private long currentBlockIndex = -1; - private final long[] currentBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; + private final long[] currentBlock = new long[numericBlockSize]; @Override public int docIDRunEnd() throws IOException { @@ -1969,8 +1980,8 @@ public int docIDRunEnd() throws IOException { @Override public long longValue() throws IOException { final int index = disi.index(); - final int blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; - final int blockInIndex = index & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; + final int blockIndex = index >>> numericBlockShift; + final int blockInIndex = index & numericBlockMask; if (blockIndex != currentBlockIndex) { assert blockIndex > currentBlockIndex : blockIndex + "<=" + currentBlockIndex; // no need to seek if the loading block is the next block @@ -2038,8 +2049,8 @@ public BlockLoader.Block tryRead( try (var singletonLongBuilder = singletonLongBuilder(factory, toDouble, valueCount, toInt)) { for (int i = 0; i < valueCount;) { final int index = firstIndex + i; - final int blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; - final int blockStartIndex = index & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK; + final int blockIndex = index >>> numericBlockShift; + final int blockStartIndex = index & numericBlockMask; if (blockIndex != currentBlockIndex) { assert blockIndex > currentBlockIndex : blockIndex + "<=" + currentBlockIndex; if (currentBlockIndex + 1 != blockIndex) { @@ -2048,7 +2059,7 @@ public BlockLoader.Block tryRead( currentBlockIndex = blockIndex; decoder.decode(valuesData, currentBlock); } - final int count = Math.min(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE - blockStartIndex, valueCount - i); + final int count = Math.min(numericBlockSize - blockStartIndex, valueCount - i); singletonLongBuilder.appendLongs(currentBlock, blockStartIndex, count); i += count; } @@ -2125,11 +2136,11 @@ private NumericValues getValues(NumericEntry entry, final long maxOrd) throws IO final int bitsPerOrd = maxOrd >= 0 ? PackedInts.bitsRequired(maxOrd - 1) : -1; final long[] currentBlockIndex = { -1 }; - final long[] currentBlock = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; - final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); + final long[] currentBlock = new long[numericBlockSize]; + final TSDBDocValuesEncoder decoder = new TSDBDocValuesEncoder(numericBlockSize); return index -> { - final long blockIndex = index >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; - final int blockInIndex = (int) (index & ES819TSDBDocValuesFormat.NUMERIC_BLOCK_MASK); + final long blockIndex = index >>> numericBlockShift; + final int blockInIndex = (int) (index & numericBlockMask); if (blockIndex != currentBlockIndex[0]) { // no need to seek if the loading block is the next block if (currentBlockIndex[0] + 1 != blockIndex) { @@ -2379,10 +2390,11 @@ private static class TermsDictEntry { static final class SingletonLongToSingletonOrdinalDelegate implements BlockLoader.SingletonLongBuilder { private final BlockLoader.SingletonOrdinalsBuilder builder; - private final int[] buffer = new int[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; + private final int[] buffer; - SingletonLongToSingletonOrdinalDelegate(BlockLoader.SingletonOrdinalsBuilder builder) { + SingletonLongToSingletonOrdinalDelegate(BlockLoader.SingletonOrdinalsBuilder builder, int bufferSize) { this.builder = builder; + this.buffer = new int[bufferSize]; } @Override diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesCodecDuelTests.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesCodecDuelTests.java index ab7e65959d686..283f441a3fafb 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesCodecDuelTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesCodecDuelTests.java @@ -64,7 +64,8 @@ public void testDuel() throws IOException { ESTestCase.randomIntBetween(1, 512), random().nextBoolean(), ES819TSDBDocValuesFormatTests.randomBinaryCompressionMode(), - random().nextBoolean() + random().nextBoolean(), + ES819TSDBDocValuesFormatTests.randomNumericBlockSize() ) : new TestES87TSDBDocValuesFormat(); diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/TsdbDocValueBwcTests.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/TsdbDocValueBwcTests.java index f9dc86e181638..d6549b08322c5 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/TsdbDocValueBwcTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/TsdbDocValueBwcTests.java @@ -350,7 +350,8 @@ public void testEncodeOrdinalRange() throws IOException { nextOrdinalRangeThreshold.getAsInt(), random().nextBoolean(), ES819TSDBDocValuesFormatTests.randomBinaryCompressionMode(), - randomBoolean() + randomBoolean(), + ES819TSDBDocValuesFormatTests.randomNumericBlockSize() ) ) ); diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumerVersion0.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumerVersion0.java index 9115842533453..e3e6c4177b91b 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumerVersion0.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesConsumerVersion0.java @@ -65,6 +65,8 @@ final class ES819TSDBDocValuesConsumerVersion0 extends XDocValuesConsumer { private final int minDocsPerOrdinalForOrdinalRangeEncoding; final boolean enableOptimizedMerge; private final int primarySortFieldNumber; + private final int numericBlockShift; + private final int numericBlockSize; ES819TSDBDocValuesConsumerVersion0( SegmentWriteState state, @@ -74,13 +76,17 @@ final class ES819TSDBDocValuesConsumerVersion0 extends XDocValuesConsumer { String dataCodec, String dataExtension, String metaCodec, - String metaExtension + String metaExtension, + int numericBlockShift ) throws IOException { this.termsDictBuffer = new byte[1 << 14]; this.dir = state.directory; this.minDocsPerOrdinalForOrdinalRangeEncoding = minDocsPerOrdinalForOrdinalRangeEncoding; this.primarySortFieldNumber = ES819TSDBDocValuesProducer.primarySortFieldNumber(state.segmentInfo, state.fieldInfos); this.context = state.context; + this.numericBlockShift = numericBlockShift; + this.numericBlockSize = 1 << numericBlockShift; + boolean success = false; try { final String dataName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, dataExtension); @@ -202,13 +208,13 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer, indexWriter = DirectMonotonicWriter.getInstance( meta, new ByteBuffersIndexOutput(indexOut, "temp-dv-index", "temp-dv-index"), - 1L + ((numValues - 1) >>> ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT), + 1L + ((numValues - 1) >>> numericBlockShift), ES819TSDBDocValuesFormat.DIRECT_MONOTONIC_BLOCK_SHIFT ); meta.writeInt(DIRECT_MONOTONIC_BLOCK_SHIFT); - final long[] buffer = new long[ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE]; + final long[] buffer = new long[numericBlockSize]; int bufferSize = 0; - final TSDBDocValuesEncoder encoder = new TSDBDocValuesEncoder(ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE); + final TSDBDocValuesEncoder encoder = new TSDBDocValuesEncoder(numericBlockSize); values = valuesProducer.getSortedNumeric(field); final int bitsPerOrd = maxOrd >= 0 ? PackedInts.bitsRequired(maxOrd - 1) : -1; if (valuesProducer.mergeStats.supported() && numDocsWithValue < maxDoc) { @@ -224,7 +230,7 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer, } for (int i = 0; i < count; ++i) { buffer[bufferSize++] = values.nextValue(); - if (bufferSize == ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE) { + if (bufferSize == numericBlockSize) { indexWriter.add(data.getFilePointer() - valuesDataOffset); if (maxOrd >= 0) { encoder.encodeOrdinals(buffer, data, bitsPerOrd); @@ -238,7 +244,7 @@ private long[] writeField(FieldInfo field, TsdbDocValuesProducer valuesProducer, if (bufferSize > 0) { indexWriter.add(data.getFilePointer() - valuesDataOffset); // Fill unused slots in the block with zeroes rather than junk - Arrays.fill(buffer, bufferSize, ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SIZE, 0L); + Arrays.fill(buffer, bufferSize, numericBlockSize, 0L); if (maxOrd >= 0) { encoder.encodeOrdinals(buffer, data, bitsPerOrd); } else { diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatTests.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatTests.java index e6ae8a5e48086..97eb27e1e5b15 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatTests.java @@ -80,7 +80,7 @@ public class ES819TSDBDocValuesFormatTests extends ES87TSDBDocValuesFormatTests { - private final Codec codec = new Elasticsearch92Lucene103Codec() { + protected final Codec codec = new Elasticsearch92Lucene103Codec() { final ES819TSDBDocValuesFormat docValuesFormat = new ES819TSDBDocValuesFormat( ESTestCase.randomIntBetween(2, 4096), @@ -112,7 +112,8 @@ public DocValuesConsumer fieldsConsumer(SegmentWriteState state) throws IOExcept DATA_CODEC, DATA_EXTENSION, META_CODEC, - META_EXTENSION + META_EXTENSION, + NUMERIC_BLOCK_SHIFT ); } } @@ -1414,7 +1415,8 @@ public void testLoadKeywordFieldWithIndexSorts() throws IOException { 1, // always enable range-encode random().nextBoolean(), randomBinaryCompressionMode(), - randomBoolean() + randomBoolean(), + randomNumericBlockSize() ); @Override @@ -1796,4 +1798,8 @@ public static BinaryDVCompressionMode randomBinaryCompressionMode() { BinaryDVCompressionMode[] modes = BinaryDVCompressionMode.values(); return modes[random().nextInt(modes.length)]; } + + public static int randomNumericBlockSize() { + return random().nextBoolean() ? ES819TSDBDocValuesFormat.NUMERIC_LARGE_BLOCK_SHIFT : ES819TSDBDocValuesFormat.NUMERIC_BLOCK_SHIFT; + } } diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatVariableSkipIntervalTests.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatVariableSkipIntervalTests.java index d43e253729a64..ef0dc7aaeb743 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatVariableSkipIntervalTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/es819/ES819TSDBDocValuesFormatVariableSkipIntervalTests.java @@ -24,7 +24,8 @@ protected Codec getCodec() { random().nextInt(1, 32), random().nextBoolean(), ES819TSDBDocValuesFormatTests.randomBinaryCompressionMode(), - random().nextBoolean() + random().nextBoolean(), + ES819TSDBDocValuesFormatTests.randomNumericBlockSize() ) ); } @@ -37,7 +38,8 @@ public void testSkipIndexIntervalSize() { random().nextInt(1, 32), random().nextBoolean(), ES819TSDBDocValuesFormatTests.randomBinaryCompressionMode(), - random().nextBoolean() + random().nextBoolean(), + ES819TSDBDocValuesFormatTests.randomNumericBlockSize() ) ); assertTrue(ex.getMessage().contains("skipIndexIntervalSize must be > 1"));