Самый быстрый способ прочитать 32-битное целое число из смещения в массиве байтов

Предыдущие обсуждения чтения целого числа из массива байтов в Java были сосредоточены на сценарии, в котором у вас есть четыре байта. У меня немного другой сценарий:

  • Фиксированный массив из двух миллиардов байт.

  • Вход: случайное смещение в этом массиве. (Хотя, надеюсь, достаточно неслучайный, чтобы иметь достаточно высокую частоту попаданий в кэш.)

  • Эта операция будет выполняться часто, поэтому ее необходимо выполнять как можно быстрее. Идеальным было бы наличие идиомы, которую JIT-компилятор может распознать и скомпилировать в невыровненную инструкцию загрузки, если ЦП поддерживает это. (Каждый основной ЦП платит за невыровненную поддержку при каждом доступе к памяти, даже в типичном случае, когда он не используется. Можно также воспользоваться этим, на этот раз, когда это было бы полезно.)

Какой самый быстрый способ выполнить эту операцию? Очевидно, что я могу просто написать цикл чтения-сдвига вручную, но есть ли более быстрая идиома? Или, если это нужно сделать вручную, какой вариант генерирует самый быстрый код?

Я на OpenJDK 17, если это имеет значение.

самый быстрый ->, возможно, с использованием JNI (на самом деле это не идиома, компилятор JIT не проблема, ... но у нас есть полный контроль) или/и JEP 412: Внешняя функция и API памяти. Buffer, вероятно, может выполнить операцию, но детали реализации, если это самый быстрый способ. Возможно, новый JEP 417: Векторный API поможет в этом.

user16320675 09.04.2022 10:10
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
1
75
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если вы не можете или не хотите использовать внутренние классы, вы можете использовать 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().

Другие вопросы по теме