diff --git a/server/src/main/java/org/elasticsearch/index/codec/ForUtil.java b/server/src/main/java/org/elasticsearch/index/codec/ForUtil.java index 5687b0d1b687d..5ce4b9240419a 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/ForUtil.java +++ b/server/src/main/java/org/elasticsearch/index/codec/ForUtil.java @@ -22,7 +22,9 @@ public final class ForUtil { public static final int BLOCK_SIZE = 128; private static final int BLOCK_SIZE_LOG2 = 7; - private final long[] tmp = new long[BLOCK_SIZE / 2]; + private static final ThreadLocal scratch = ThreadLocal.withInitial(() -> new long[BLOCK_SIZE / 2]); + + private ForUtil() {} private static long expandMask32(long mask32) { return mask32 | (mask32 << 32); @@ -118,7 +120,7 @@ private static void collapse32(long[] arr) { } /** Encode 128 integers from {@code longs} into {@code out}. */ - public void encode(long[] longs, int bitsPerValue, DataOutput out) throws IOException { + public static void encode(long[] longs, int bitsPerValue, DataOutput out) throws IOException { final int nextPrimitive; final int numLongs; if (bitsPerValue <= 8) { @@ -138,6 +140,7 @@ public void encode(long[] longs, int bitsPerValue, DataOutput out) throws IOExce final int numLongsPerShift = bitsPerValue * 2; int idx = 0; int shift = nextPrimitive - bitsPerValue; + final long[] tmp = scratch.get(); for (int i = 0; i < numLongsPerShift; ++i) { tmp[i] = longs[idx++] << shift; } @@ -191,7 +194,7 @@ public void encode(long[] longs, int bitsPerValue, DataOutput out) throws IOExce } /** Number of bytes required to encode 128 integers of {@code bitsPerValue} bits per value. */ - public int numBytes(int bitsPerValue) { + public static int numBytes(int bitsPerValue) { return bitsPerValue << (BLOCK_SIZE_LOG2 - 3); } @@ -299,7 +302,8 @@ private static void shiftLongs(long[] a, int count, long[] b, int bi, int shift, private static final long MASK32_24 = MASKS32[24]; /** Decode 128 integers into {@code longs}. */ - public void decode(int bitsPerValue, DataInput in, long[] longs) throws IOException { + public static void decode(int bitsPerValue, DataInput in, long[] longs) throws IOException { + final long[] tmp = scratch.get(); switch (bitsPerValue) { case 1: decode1(in, tmp, longs); @@ -410,7 +414,8 @@ public void decode(int bitsPerValue, DataInput in, long[] longs) throws IOExcept * [0..63], and values [64..127] are encoded in the low-order bits of {@code longs} [0..63]. This * representation may allow subsequent operations to be performed on two values at a time. */ - public void decodeTo32(int bitsPerValue, DataInput in, long[] longs) throws IOException { + public static void decodeTo32(int bitsPerValue, DataInput in, long[] longs) throws IOException { + final long[] tmp = scratch.get(); switch (bitsPerValue) { case 1: decode1(in, tmp, longs); diff --git a/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsReader.java b/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsReader.java index 11bd90cd31610..1aada2a153c3c 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsReader.java +++ b/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsReader.java @@ -61,8 +61,6 @@ final class ES812PostingsReader extends PostingsReaderBase { private final IndexInput posIn; private final IndexInput payIn; - private final int version; - /** Sole constructor. */ ES812PostingsReader(SegmentReadState state) throws IOException { boolean success = false; @@ -78,7 +76,7 @@ final class ES812PostingsReader extends PostingsReaderBase { String docName = IndexFileNames.segmentFileName(state.segmentInfo.name, state.segmentSuffix, ES812PostingsFormat.DOC_EXTENSION); try { docIn = state.directory.openInput(docName, state.context); - version = CodecUtil.checkIndexHeader( + int version = CodecUtil.checkIndexHeader( docIn, DOC_CODEC, VERSION_START, @@ -279,7 +277,7 @@ public ImpactsEnum impacts(FieldInfo fieldInfo, BlockTermState state, int flags) final class BlockDocsEnum extends PostingsEnum { - final PForUtil pforUtil = new PForUtil(new ForUtil()); + final PForUtil pforUtil = new PForUtil(); private final long[] docBuffer = new long[BLOCK_SIZE + 1]; private final long[] freqBuffer = new long[BLOCK_SIZE]; @@ -526,7 +524,7 @@ public long cost() { // Also handles payloads + offsets final class EverythingEnum extends PostingsEnum { - final PForUtil pforUtil = new PForUtil(new ForUtil()); + final PForUtil pforUtil = new PForUtil(); private final long[] docBuffer = new long[BLOCK_SIZE + 1]; private final long[] freqBuffer = new long[BLOCK_SIZE + 1]; @@ -999,7 +997,7 @@ public long cost() { final class BlockImpactsDocsEnum extends ImpactsEnum { - final PForUtil pforUtil = new PForUtil(new ForUtil()); + final PForUtil pforUtil = new PForUtil(); private final long[] docBuffer = new long[BLOCK_SIZE + 1]; private final long[] freqBuffer = new long[BLOCK_SIZE]; @@ -1196,7 +1194,7 @@ public long cost() { final class BlockImpactsPostingsEnum extends ImpactsEnum { - final PForUtil pforUtil = new PForUtil(new ForUtil()); + final PForUtil pforUtil = new PForUtil(); private final long[] docBuffer = new long[BLOCK_SIZE]; private final long[] freqBuffer = new long[BLOCK_SIZE]; @@ -1476,7 +1474,7 @@ public long cost() { final class BlockImpactsEverythingEnum extends ImpactsEnum { - final PForUtil pforUtil = new PForUtil(new ForUtil()); + final PForUtil pforUtil = new PForUtil(); private final long[] docBuffer = new long[BLOCK_SIZE]; private final long[] freqBuffer = new long[BLOCK_SIZE]; diff --git a/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsWriter.java b/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsWriter.java index cc95b4ffcfacf..f604f02439e08 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsWriter.java +++ b/server/src/main/java/org/elasticsearch/index/codec/postings/ES812PostingsWriter.java @@ -35,7 +35,6 @@ import org.apache.lucene.util.BitUtil; import org.apache.lucene.util.BytesRef; import org.elasticsearch.core.IOUtils; -import org.elasticsearch.index.codec.ForUtil; import org.elasticsearch.index.codec.postings.ES812PostingsFormat.IntBlockTermState; import java.io.IOException; @@ -110,7 +109,7 @@ final class ES812PostingsWriter extends PushPostingsWriterBase { boolean success = false; try { CodecUtil.writeIndexHeader(docOut, DOC_CODEC, VERSION_CURRENT, state.segmentInfo.getId(), state.segmentSuffix); - pforUtil = new PForUtil(new ForUtil()); + pforUtil = new PForUtil(); if (state.fieldInfos.hasProx()) { posDeltaBuffer = new long[BLOCK_SIZE]; String posFileName = IndexFileNames.segmentFileName( diff --git a/server/src/main/java/org/elasticsearch/index/codec/postings/PForUtil.java b/server/src/main/java/org/elasticsearch/index/codec/postings/PForUtil.java index 46ab0b0d00671..d8dd33cd6168f 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/postings/PForUtil.java +++ b/server/src/main/java/org/elasticsearch/index/codec/postings/PForUtil.java @@ -52,14 +52,12 @@ static boolean allEqual(long[] l) { return true; } - private final ForUtil forUtil; // buffer for reading exception data; each exception uses two bytes (pos + high-order bits of the // exception) private final byte[] exceptionBuff = new byte[MAX_EXCEPTIONS * 2]; - PForUtil(ForUtil forUtil) { + PForUtil() { assert ForUtil.BLOCK_SIZE <= 256 : "blocksize must fit in one byte. got " + ForUtil.BLOCK_SIZE; - this.forUtil = forUtil; } /** Encode 128 integers from {@code longs} into {@code out}. */ @@ -114,7 +112,7 @@ void encode(long[] longs, DataOutput out) throws IOException { } else { final int token = (numExceptions << 5) | patchedBitsRequired; out.writeByte((byte) token); - forUtil.encode(longs, patchedBitsRequired, out); + ForUtil.encode(longs, patchedBitsRequired, out); } out.writeBytes(exceptions, exceptions.length); } @@ -127,7 +125,7 @@ void decode(DataInput in, long[] longs) throws IOException { if (bitsPerValue == 0) { Arrays.fill(longs, 0, ForUtil.BLOCK_SIZE, in.readVLong()); } else { - forUtil.decode(bitsPerValue, in, longs); + ForUtil.decode(bitsPerValue, in, longs); } for (int i = 0; i < numExceptions; ++i) { longs[Byte.toUnsignedInt(in.readByte())] |= Byte.toUnsignedLong(in.readByte()) << bitsPerValue; @@ -153,7 +151,7 @@ void decodeAndPrefixSum(DataInput in, long base, long[] longs) throws IOExceptio } } else { // decode the deltas then apply the prefix sum logic - forUtil.decodeTo32(bitsPerValue, in, longs); + ForUtil.decodeTo32(bitsPerValue, in, longs); prefixSum32(longs, base); } } else { @@ -161,7 +159,7 @@ void decodeAndPrefixSum(DataInput in, long base, long[] longs) throws IOExceptio if (bitsPerValue == 0) { fillSameValue32(longs, in.readVLong()); } else { - forUtil.decodeTo32(bitsPerValue, in, longs); + ForUtil.decodeTo32(bitsPerValue, in, longs); } applyExceptions32(bitsPerValue, numExceptions, in, longs); prefixSum32(longs, base); @@ -177,7 +175,7 @@ void skip(DataInput in) throws IOException { in.readVLong(); in.skipBytes((numExceptions << 1)); } else { - in.skipBytes(forUtil.numBytes(bitsPerValue) + (numExceptions << 1)); + in.skipBytes(ForUtil.numBytes(bitsPerValue) + (numExceptions << 1)); } } diff --git a/server/src/main/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtil.java b/server/src/main/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtil.java index 303c66309a23f..4ed6a0e7277ab 100644 --- a/server/src/main/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtil.java +++ b/server/src/main/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtil.java @@ -20,7 +20,6 @@ public class DocValuesForUtil { private static final int BITS_IN_FIVE_BYTES = 5 * Byte.SIZE; private static final int BITS_IN_SIX_BYTES = 6 * Byte.SIZE; private static final int BITS_IN_SEVEN_BYTES = 7 * Byte.SIZE; - private final ForUtil forUtil = new ForUtil(); private final int blockSize; private final byte[] encoded; @@ -50,7 +49,7 @@ public static int roundBits(int bitsPerValue) { public void encode(long[] in, int bitsPerValue, final DataOutput out) throws IOException { if (bitsPerValue <= 24) { // these bpvs are handled efficiently by ForUtil - forUtil.encode(in, bitsPerValue, out); + ForUtil.encode(in, bitsPerValue, out); } else if (bitsPerValue <= 32) { collapse32(in); for (int i = 0; i < blockSize / 2; ++i) { @@ -76,7 +75,7 @@ private void encodeFiveSixOrSevenBytesPerValue(long[] in, int bitsPerValue, fina public void decode(int bitsPerValue, final DataInput in, long[] out) throws IOException { if (bitsPerValue <= 24) { - forUtil.decode(bitsPerValue, in, out); + ForUtil.decode(bitsPerValue, in, out); } else if (bitsPerValue <= 32) { in.readLongs(out, 0, blockSize / 2); expand32(out); diff --git a/server/src/test/java/org/elasticsearch/index/codec/ForUtilTests.java b/server/src/test/java/org/elasticsearch/index/codec/ForUtilTests.java index 5d9052203c5f4..55ad8fabd044f 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/ForUtilTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/ForUtilTests.java @@ -53,7 +53,6 @@ public void testEncodeDecode() throws IOException { { // encode IndexOutput out = d.createOutput("test.bin", IOContext.DEFAULT); - final ForUtil forUtil = new ForUtil(); for (int i = 0; i < iterations; ++i) { long[] source = new long[ForUtil.BLOCK_SIZE]; @@ -64,7 +63,7 @@ public void testEncodeDecode() throws IOException { } final int bpv = PackedInts.bitsRequired(or); out.writeByte((byte) bpv); - forUtil.encode(source, bpv, out); + ForUtil.encode(source, bpv, out); } endPointer = out.getFilePointer(); out.close(); @@ -73,12 +72,11 @@ public void testEncodeDecode() throws IOException { { // decode IndexInput in = d.openInput("test.bin", IOContext.READONCE); - final ForUtil forUtil = new ForUtil(); for (int i = 0; i < iterations; ++i) { final int bitsPerValue = in.readByte(); final long currentFilePointer = in.getFilePointer(); final long[] restored = new long[ForUtil.BLOCK_SIZE]; - forUtil.decode(bitsPerValue, in, restored); + ForUtil.decode(bitsPerValue, in, restored); int[] ints = new int[ForUtil.BLOCK_SIZE]; for (int j = 0; j < ForUtil.BLOCK_SIZE; ++j) { ints[j] = Math.toIntExact(restored[j]); @@ -88,7 +86,7 @@ public void testEncodeDecode() throws IOException { ArrayUtil.copyOfSubArray(values, i * ForUtil.BLOCK_SIZE, (i + 1) * ForUtil.BLOCK_SIZE), ints ); - assertEquals(forUtil.numBytes(bitsPerValue), in.getFilePointer() - currentFilePointer); + assertEquals(ForUtil.numBytes(bitsPerValue), in.getFilePointer() - currentFilePointer); } assertEquals(endPointer, in.getFilePointer()); in.close(); diff --git a/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtilTests.java b/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtilTests.java index f766d2148a96e..aa395ab3eec89 100644 --- a/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtilTests.java +++ b/server/src/test/java/org/elasticsearch/index/codec/tsdb/DocValuesForUtilTests.java @@ -30,8 +30,6 @@ import java.util.Random; public class DocValuesForUtilTests extends LuceneTestCase { - private final ES87TSDBDocValuesEncoder encoder = new ES87TSDBDocValuesEncoder(); - private static final ForUtil forUtil = new ForUtil(); public void testEncodeDecode() throws IOException { final int iterations = RandomNumbers.randomIntBetween(random(), 50, 1000); @@ -105,14 +103,14 @@ public void testEncodeDecodeBitsPerValue() throws IOException { // Encode DataOutput dataOutput = new ByteArrayDataOutput(dataOutputBuffer); long[] encodeBuffer = Arrays.copyOf(values, values.length); - forUtil.encode(encodeBuffer, bitsPerValue, dataOutput); + ForUtil.encode(encodeBuffer, bitsPerValue, dataOutput); // Prepare for decoding DataInput dataInput = new ByteArrayDataInput(dataInputBuffer); System.arraycopy(dataOutputBuffer, 0, dataInputBuffer, 0, dataOutputBuffer.length); // Decode - forUtil.decode(bitsPerValue, dataInput, decodeBuffer); + ForUtil.decode(bitsPerValue, dataInput, decodeBuffer); assertArrayEquals(decodeBuffer, values); }