Skip to content

Commit 2b097db

Browse files
authored
Use varhandles for primitive type conversion in more places (#85577)
Add more uses of the var handles byte conversions.
1 parent 1d4534f commit 2b097db

File tree

6 files changed

+206
-65
lines changed

6 files changed

+206
-65
lines changed

docs/changelog/85577.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
pr: 85577
2+
summary: Use varhandles for primitive type conversion in more places
3+
area: Infra/Core
4+
type: enhancement
5+
issues:
6+
- 78823

server/src/main/java/org/elasticsearch/common/Numbers.java

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,60 +9,57 @@
99
package org.elasticsearch.common;
1010

1111
import org.apache.lucene.util.BytesRef;
12+
import org.elasticsearch.common.util.ByteUtils;
1213

13-
import java.lang.invoke.MethodHandles;
14-
import java.lang.invoke.VarHandle;
1514
import java.math.BigDecimal;
1615
import java.math.BigInteger;
17-
import java.nio.ByteOrder;
1816

1917
/**
2018
* A set of utilities for numbers.
2119
*/
2220
public final class Numbers {
23-
24-
private static final VarHandle BIG_ENDIAN_SHORT = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.BIG_ENDIAN);
25-
26-
private static final VarHandle BIG_ENDIAN_INT = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
27-
28-
private static final VarHandle BIG_ENDIAN_LONG = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);
29-
3021
private static final BigInteger MAX_LONG_VALUE = BigInteger.valueOf(Long.MAX_VALUE);
3122
private static final BigInteger MIN_LONG_VALUE = BigInteger.valueOf(Long.MIN_VALUE);
3223

3324
private Numbers() {}
3425

3526
public static short bytesToShort(byte[] bytes, int offset) {
36-
return (short) BIG_ENDIAN_SHORT.get(bytes, offset);
27+
return ByteUtils.readShortBE(bytes, offset);
3728
}
3829

3930
public static int bytesToInt(byte[] bytes, int offset) {
40-
return (int) BIG_ENDIAN_INT.get(bytes, offset);
31+
return ByteUtils.readIntBE(bytes, offset);
4132
}
4233

4334
public static long bytesToLong(byte[] bytes, int offset) {
44-
return (long) BIG_ENDIAN_LONG.get(bytes, offset);
35+
return ByteUtils.readLongBE(bytes, offset);
4536
}
4637

4738
public static long bytesToLong(BytesRef bytes) {
4839
return bytesToLong(bytes.bytes, bytes.offset);
4940
}
5041

42+
/**
43+
* Converts an int to a byte array.
44+
*
45+
* @param val The int to convert to a byte array
46+
* @return The byte array converted
47+
*/
5148
public static byte[] intToBytes(int val) {
5249
byte[] arr = new byte[4];
53-
BIG_ENDIAN_INT.set(arr, 0, val);
50+
ByteUtils.writeIntBE(val, arr, 0);
5451
return arr;
5552
}
5653

5754
/**
58-
* Converts an int to a byte array.
55+
* Converts a short to a byte array.
5956
*
60-
* @param val The int to convert to a byte array
57+
* @param val The short to convert to a byte array
6158
* @return The byte array converted
6259
*/
6360
public static byte[] shortToBytes(int val) {
6461
byte[] arr = new byte[2];
65-
BIG_ENDIAN_SHORT.set(arr, 0, (short) val);
62+
ByteUtils.writeShortBE((short) val, arr, 0);
6663
return arr;
6764
}
6865

@@ -74,7 +71,7 @@ public static byte[] shortToBytes(int val) {
7471
*/
7572
public static byte[] longToBytes(long val) {
7673
byte[] arr = new byte[8];
77-
BIG_ENDIAN_LONG.set(arr, 0, val);
74+
ByteUtils.writeLongBE(val, arr, 0);
7875
return arr;
7976
}
8077

server/src/main/java/org/elasticsearch/common/io/stream/StreamOutput.java

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.elasticsearch.common.io.stream.Writeable.Writer;
2525
import org.elasticsearch.common.settings.SecureString;
2626
import org.elasticsearch.common.text.Text;
27+
import org.elasticsearch.common.util.ByteUtils;
2728
import org.elasticsearch.common.util.concurrent.EsRejectedExecutionException;
2829
import org.elasticsearch.core.CharArrays;
2930
import org.elasticsearch.core.Nullable;
@@ -193,8 +194,7 @@ public void writeBytesRef(BytesRef bytes) throws IOException {
193194

194195
public final void writeShort(short v) throws IOException {
195196
final byte[] buffer = scratch.get();
196-
buffer[0] = (byte) (v >> 8);
197-
buffer[1] = (byte) v;
197+
ByteUtils.writeShortBE(v, buffer, 0);
198198
writeBytes(buffer, 0, 2);
199199
}
200200

@@ -203,10 +203,7 @@ public final void writeShort(short v) throws IOException {
203203
*/
204204
public void writeInt(int i) throws IOException {
205205
final byte[] buffer = scratch.get();
206-
buffer[0] = (byte) (i >> 24);
207-
buffer[1] = (byte) (i >> 16);
208-
buffer[2] = (byte) (i >> 8);
209-
buffer[3] = (byte) i;
206+
ByteUtils.writeIntBE(i, buffer, 0);
210207
writeBytes(buffer, 0, 4);
211208
}
212209

@@ -246,14 +243,7 @@ public void writeVInt(int i) throws IOException {
246243
*/
247244
public void writeLong(long i) throws IOException {
248245
final byte[] buffer = scratch.get();
249-
buffer[0] = (byte) (i >> 56);
250-
buffer[1] = (byte) (i >> 48);
251-
buffer[2] = (byte) (i >> 40);
252-
buffer[3] = (byte) (i >> 32);
253-
buffer[4] = (byte) (i >> 24);
254-
buffer[5] = (byte) (i >> 16);
255-
buffer[6] = (byte) (i >> 8);
256-
buffer[7] = (byte) i;
246+
ByteUtils.writeLongBE(i, buffer, 0);
257247
writeBytes(buffer, 0, 8);
258248
}
259249

server/src/main/java/org/elasticsearch/common/util/ByteUtils.java

Lines changed: 120 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ public enum ByteUtils {
2323

2424
public static final VarHandle BIG_ENDIAN_LONG = MethodHandles.byteArrayViewVarHandle(long[].class, ByteOrder.BIG_ENDIAN);
2525

26+
private static final VarHandle BIG_ENDIAN_SHORT = MethodHandles.byteArrayViewVarHandle(short[].class, ByteOrder.BIG_ENDIAN);
27+
28+
private static final VarHandle BIG_ENDIAN_INT = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.BIG_ENDIAN);
29+
2630
/** Zig-zag decode. */
2731
public static long zigZagDecode(long n) {
2832
return ((n >>> 1) ^ -(n & 1));
@@ -33,54 +37,150 @@ public static long zigZagEncode(long n) {
3337
return (n >> 63) ^ (n << 1);
3438
}
3539

36-
/** Write a long in little-endian format. */
37-
public static void writeLongLE(long l, byte[] arr, int offset) {
38-
LITTLE_ENDIAN_LONG.set(arr, offset, l);
40+
/**
41+
* Converts a long to a byte array in little endian format.
42+
*
43+
* @param val The long to convert to a byte array
44+
* @param arr The byte array to write the long value in little endian layout
45+
* @param offset The offset where in the array to write to
46+
*/
47+
public static void writeLongLE(long val, byte[] arr, int offset) {
48+
LITTLE_ENDIAN_LONG.set(arr, offset, val);
3949
}
4050

41-
/** Write a long in little-endian format. */
51+
/**
52+
* Converts a byte array written in little endian format to a long.
53+
*
54+
* @param arr The byte array to read from in little endian layout
55+
* @param offset The offset where in the array to read from
56+
*/
4257
public static long readLongLE(byte[] arr, int offset) {
4358
return (long) LITTLE_ENDIAN_LONG.get(arr, offset);
4459
}
4560

46-
/** Write a long in big-endian format. */
47-
public static void writeLongBE(long l, byte[] arr, int offset) {
48-
BIG_ENDIAN_LONG.set(arr, offset, l);
61+
/**
62+
* Converts a long to a byte array in big endian format.
63+
*
64+
* @param val The long to convert to a byte array
65+
* @param arr The byte array to write the long value in big endian layout
66+
* @param offset The offset where in the array to write to
67+
*/
68+
public static void writeLongBE(long val, byte[] arr, int offset) {
69+
BIG_ENDIAN_LONG.set(arr, offset, val);
4970
}
5071

51-
/** Write a long in big-endian format. */
72+
/**
73+
* Converts a byte array written in big endian format to a long.
74+
*
75+
* @param arr The byte array to read from in big endian layout
76+
* @param offset The offset where in the array to read from
77+
*/
5278
public static long readLongBE(byte[] arr, int offset) {
5379
return (long) BIG_ENDIAN_LONG.get(arr, offset);
5480
}
5581

56-
/** Write an int in little-endian format. */
57-
public static void writeIntLE(int l, byte[] arr, int offset) {
58-
LITTLE_ENDIAN_INT.set(arr, offset, l);
82+
/**
83+
* Converts an int to a byte array in little endian format.
84+
*
85+
* @param val The int to convert to a byte array
86+
* @param arr The byte array to write the int value in little endian layout
87+
* @param offset The offset where in the array to write to
88+
*/
89+
public static void writeIntLE(int val, byte[] arr, int offset) {
90+
LITTLE_ENDIAN_INT.set(arr, offset, val);
5991
}
6092

61-
/** Read an int in little-endian format. */
93+
/**
94+
* Converts a byte array written in little endian format to an int.
95+
*
96+
* @param arr The byte array to read from in little endian layout
97+
* @param offset The offset where in the array to read from
98+
*/
6299
public static int readIntLE(byte[] arr, int offset) {
63100
return (int) LITTLE_ENDIAN_INT.get(arr, offset);
64101
}
65102

66-
/** Write a double in little-endian format. */
67-
public static void writeDoubleLE(double d, byte[] arr, int offset) {
68-
writeLongLE(Double.doubleToRawLongBits(d), arr, offset);
103+
/**
104+
* Converts a double to a byte array in little endian format.
105+
*
106+
* @param val The double to convert to a byte array
107+
* @param arr The byte array to write the double value in little endian layout
108+
* @param offset The offset where in the array to write to
109+
*/
110+
public static void writeDoubleLE(double val, byte[] arr, int offset) {
111+
writeLongLE(Double.doubleToRawLongBits(val), arr, offset);
69112
}
70113

71-
/** Read a double in little-endian format. */
114+
/**
115+
* Converts a byte array written in little endian format to a double.
116+
*
117+
* @param arr The byte array to read from in little endian layout
118+
* @param offset The offset where in the array to read from
119+
*/
72120
public static double readDoubleLE(byte[] arr, int offset) {
73121
return Double.longBitsToDouble(readLongLE(arr, offset));
74122
}
75123

76-
/** Write a float in little-endian format. */
77-
public static void writeFloatLE(float d, byte[] arr, int offset) {
78-
writeIntLE(Float.floatToRawIntBits(d), arr, offset);
124+
/**
125+
* Converts a float to a byte array in little endian format.
126+
*
127+
* @param val The float to convert to a byte array
128+
* @param arr The byte array to write the float value in little endian layout
129+
* @param offset The offset where in the array to write to
130+
*/
131+
public static void writeFloatLE(float val, byte[] arr, int offset) {
132+
writeIntLE(Float.floatToRawIntBits(val), arr, offset);
79133
}
80134

81-
/** Read a float in little-endian format. */
135+
/**
136+
* Converts a byte array written in little endian format to a float.
137+
*
138+
* @param arr The byte array to read from in little endian layout
139+
* @param offset The offset where in the array to read from
140+
*/
82141
public static float readFloatLE(byte[] arr, int offset) {
83142
return Float.intBitsToFloat(readIntLE(arr, offset));
84143
}
85144

145+
/**
146+
* Converts an int to a byte array in big endian format.
147+
*
148+
* @param val The int to convert to a byte array
149+
* @param arr The byte array to write the int value in big endian layout
150+
* @param offset The offset where in the array to write to
151+
*/
152+
public static void writeIntBE(int val, byte[] arr, int offset) {
153+
BIG_ENDIAN_INT.set(arr, offset, val);
154+
}
155+
156+
/**
157+
* Converts a byte array written in big endian format to an int.
158+
*
159+
* @param arr The byte array to read from in big endian layout
160+
* @param offset The offset where in the array to read from
161+
*/
162+
public static int readIntBE(byte[] arr, int offset) {
163+
return (int) BIG_ENDIAN_INT.get(arr, offset);
164+
}
165+
166+
/**
167+
* Converts a short to a byte array in big endian format.
168+
*
169+
* @param val The short to convert to a byte array
170+
* @param arr The byte array to write the short value in big endian layout
171+
* @param offset The offset where in the array to write to
172+
*/
173+
public static void writeShortBE(short val, byte[] arr, int offset) {
174+
BIG_ENDIAN_SHORT.set(arr, offset, val);
175+
}
176+
177+
/**
178+
* Converts a byte array written in big endian format to a short.
179+
*
180+
* @param arr The byte array to read from in big endian layout
181+
* @param offset The offset where in the array to read from
182+
*/
183+
public static short readShortBE(byte[] arr, int offset) {
184+
return (short) BIG_ENDIAN_SHORT.get(arr, offset);
185+
}
86186
}

server/src/main/java/org/elasticsearch/transport/ReuseBuffersLZ4BlockOutputStream.java

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
import net.jpountz.util.SafeUtils;
2323

2424
import org.apache.lucene.util.BytesRef;
25+
import org.elasticsearch.common.util.ByteUtils;
2526

2627
import java.io.FilterOutputStream;
2728
import java.io.IOException;
@@ -208,10 +209,10 @@ private void flushBufferedData() throws IOException {
208209
}
209210

210211
compressedBuffer[MAGIC_LENGTH] = (byte) (compressMethod | compressionLevel);
211-
writeIntLE(compressedLength, compressedBuffer, MAGIC_LENGTH + 1);
212-
writeIntLE(o, compressedBuffer, MAGIC_LENGTH + 5);
212+
ByteUtils.writeIntLE(compressedLength, compressedBuffer, MAGIC_LENGTH + 1);
213+
ByteUtils.writeIntLE(o, compressedBuffer, MAGIC_LENGTH + 5);
213214
// Write 0 for checksum. We do not read it on decompress.
214-
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 9);
215+
ByteUtils.writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 9);
215216
assert MAGIC_LENGTH + 13 == HEADER_LENGTH;
216217
out.write(compressedBuffer, 0, HEADER_LENGTH + compressedLength);
217218
o = 0;
@@ -247,22 +248,15 @@ public void finish() throws IOException {
247248
ensureNotFinished();
248249
flushBufferedData();
249250
compressedBuffer[MAGIC_LENGTH] = (byte) (COMPRESSION_METHOD_RAW | compressionLevel);
250-
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 1);
251-
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 5);
252-
writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 9);
251+
ByteUtils.writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 1);
252+
ByteUtils.writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 5);
253+
ByteUtils.writeIntLE(0, compressedBuffer, MAGIC_LENGTH + 9);
253254
assert MAGIC_LENGTH + 13 == HEADER_LENGTH;
254255
out.write(compressedBuffer, 0, HEADER_LENGTH);
255256
finished = true;
256257
out.flush();
257258
}
258259

259-
private static void writeIntLE(int i, byte[] buf, int off) {
260-
buf[off++] = (byte) i;
261-
buf[off++] = (byte) (i >>> 8);
262-
buf[off++] = (byte) (i >>> 16);
263-
buf[off++] = (byte) (i >>> 24);
264-
}
265-
266260
@Override
267261
public String toString() {
268262
return getClass().getSimpleName() + "(out=" + out + ", blockSize=" + blockSize + ", compressor=" + compressor + ")";

0 commit comments

Comments
 (0)