Предыдущие обсуждения чтения целого числа из массива байтов в Java были сосредоточены на сценарии, в котором у вас есть четыре байта. У меня немного другой сценарий:
Фиксированный массив из двух миллиардов байт.
Вход: случайное смещение в этом массиве. (Хотя, надеюсь, достаточно неслучайный, чтобы иметь достаточно высокую частоту попаданий в кэш.)
Эта операция будет выполняться часто, поэтому ее необходимо выполнять как можно быстрее. Идеальным было бы наличие идиомы, которую JIT-компилятор может распознать и скомпилировать в невыровненную инструкцию загрузки, если ЦП поддерживает это. (Каждый основной ЦП платит за невыровненную поддержку при каждом доступе к памяти, даже в типичном случае, когда он не используется. Можно также воспользоваться этим, на этот раз, когда это было бы полезно.)
Какой самый быстрый способ выполнить эту операцию? Очевидно, что я могу просто написать цикл чтения-сдвига вручную, но есть ли более быстрая идиома? Или, если это нужно сделать вручную, какой вариант генерирует самый быстрый код?
Я на OpenJDK 17, если это имеет значение.
Если вы не можете или не хотите использовать внутренние классы, вы можете использовать VarHandle
для доступа к этому:
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);
}
Хотя это добавляет некоторую косвенность, в конечном итоге он вызовет Unsafe.unalignedAccess()
, когда поддерживается.
И если вы используете лучшие практики (VarHandle
в поле static final
...), JIT обычно может встроить все до Unsafe.unalignedAccess()
.
самый быстрый ->, возможно, с использованием JNI (на самом деле это не идиома, компилятор JIT не проблема, ... но у нас есть полный контроль) или/и JEP 412: Внешняя функция и API памяти.
Buffer
, вероятно, может выполнить операцию, но детали реализации, если это самый быстрый способ. Возможно, новый JEP 417: Векторный API поможет в этом.