On Thu, 20 Jul 2023 14:53:36 GMT, Glavo <d...@openjdk.org> wrote:

>> @mcimadamore I compared the performance of `ByteBuffer` and `VarHandle` 
>> using a JMH benchmark:
>> 
>> 
>> public class ByteArray {
>> 
>>     private byte[] array;
>>     private ByteBuffer byteBuffer;
>> 
>>     private static final VarHandle INT = 
>> MethodHandles.byteArrayViewVarHandle(int[].class, LITTLE_ENDIAN);
>>     private static final VarHandle LONG = 
>> MethodHandles.byteArrayViewVarHandle(long[].class, LITTLE_ENDIAN);
>> 
>>     @Setup
>>     public void setup() {
>>         array = new byte[8];
>>         byteBuffer = ByteBuffer.wrap(array).order(LITTLE_ENDIAN);
>> 
>>         new Random(0).nextBytes(array);
>>     }
>> 
>>     @Benchmark
>>     public byte readByte() {
>>         return array[0];
>>     }
>> 
>>     @Benchmark
>>     public byte readByteFromBuffer() {
>>         return byteBuffer.get(0);
>>     }
>> 
>>     @Benchmark
>>     public int readInt() {
>>         return (int) INT.get(array, 0);
>>     }
>> 
>>     @Benchmark
>>     public int readIntFromBuffer() {
>>         return byteBuffer.getInt(0);
>>     }
>> 
>> 
>>     @Benchmark
>>     public long readLong() {
>>         return (long) LONG.get(array, 0);
>>     }
>> 
>>     @Benchmark
>>     public long readLongFromBuffer() {
>>         return byteBuffer.getLong(0);
>>     }
>> }
>> 
>> 
>> Result:
>> 
>> Benchmark                      Mode  Cnt        Score       Error   Units
>> ByteArray.readByte            thrpt    5  1270230.180 ± 29172.551  ops/ms
>> ByteArray.readByteFromBuffer  thrpt    5   623862.080 ± 12167.410  ops/ms
>> ByteArray.readInt             thrpt    5  1252719.463 ± 77598.672  ops/ms
>> ByteArray.readIntFromBuffer   thrpt    5   571070.474 ±  1500.426  ops/ms
>> ByteArray.readLong            thrpt    5  1262720.686 ±   728.100  ops/ms
>> ByteArray.readLongFromBuffer  thrpt    5   571594.800 ±  3376.735  ops/ms
>> 
>> 
>> In this result, ByteBuffer is much slower than VarHandle. Am I doing 
>> something wrong? What conditions are needed to make the performance of 
>> ByteBuffer close to that of Unsafe?
>
> I tried a few more. It looks like the JIT is able to optimize the ByteBuffer 
> away pretty well by keeping it only as a local variable without escaping.

It seems that as long as the `ByteBuffer` is stored in a field (even if it is 
`static final`), the JIT compiler cannot completely eliminate the overhead of 
the `ByteBuffer`.

@mcimadamore I think your suggested changes for `DataInputStream` is dubious, 
it's likely to introduce non-trivial additional overhead. The correct change 
may be like this:


public final double readDouble() throws IOException {
    readFully(readBuffer, 0, 8);
-   return ByteArray.getDouble(readBuffer, 0);
+   return ByteBuffer.wrap(readBuffer).getDouble(0);
}


However this change can also increase the warmup time and allocate many small 
objects before C2 compiles it.

-------------

PR Review Comment: https://git.openjdk.org/jdk/pull/14636#discussion_r1269617039

Reply via email to