Search code examples
javaarraysperformancejava-17

Fastest way to read a 32-bit integer from an offset in a byte array


Previous discussions on reading an integer from a byte array in Java, focus on the scenario where what you have is four bytes. I have a slightly different scenario:

  • A fixed array of two billion bytes.

  • Input: a random offset into that array. (Though hopefully sufficiently nonrandom to have a reasonably high cache hit rate.)

  • This operation will happen frequently, such that it needs to run as fast as possible. The ideal would be if there is an idiom that the JIT compiler can recognize and compile into an unaligned load instruction, if the CPU supports such. (Every mainstream CPU pays for unaligned support in every memory access, even in the typical case when it's not used. Might as well take advantage of it, this one time when it would be useful.)

What's the the fastest way to perform this operation? Obviously I can just write the read-shift loop by hand, but is there a faster idiom? Or if it is to be done by hand, which variant generates the fastest code?

I'm on OpenJDK 17, if that matters.


Solution

  • If you do not can or wish to use internal classes, you can use a VarHandle to access this:

    private static final VarHandle READ_ARRAY = MethodHandles.byteArrayViewVarHandle(int[].class, ByteOrder.nativeOrder());
    
    public static void main(String[] args) {
        byte[] arr = ...;
        
        int pos = ...; // pos is the index into the byte array, and may be unaligned.
        int result = (int) READ_ARRAY.get(arr, pos);
    
    
        System.out.println(result);
    }
    

    While this adds some indirection, ultimately it will call Unsafe.unalignedAccess() when supported.
    And if you are using best practices (VarHandle in a static final field...), the JIT can usually inline everything down to Unsafe.unalignedAccess().