Как реализовать JIT-компилятор ART

Среда выполнения Android (ART) включает JIT-компилятор с профилированием кода, который постоянно повышает производительность приложений Android во время их работы. JIT-компилятор дополняет существующий в ART AOT-компилятор и повышает производительность во время выполнения, экономит место в хранилище и ускоряет обновление приложений и системы. Кроме того, он позволяет избежать замедления работы системы при автоматическом обновлении приложений или их перекомпиляции во время беспроводного обновления.

Хотя JIT и AOT используют один и тот же компилятор с похожим набором оптимизаций, сгенерированный код может быть неидентичным. JIT использует информацию о типах во время выполнения, может лучше встраивать код и позволяет выполнять компиляцию с заменой стека (OSR), что приводит к созданию немного другого кода.

Архитектура JIT

Архитектура JIT
Рисунок 1. архитектуру JIT;

JIT-компиляция

JIT-компиляция включает следующие действия:

Компиляция на основе профиля
Рисунок 2. Компиляция с учетом профиля.
  1. Пользователь запускает приложение, и ART загружает .dexфайл.
    • Если файл .oat (двоичный файл AOT для файла .dex ) доступен, ART использует его напрямую. Хотя файлы .oat создаются регулярно, они не всегда содержат скомпилированный код (двоичный файл AOT).
    • Если файл .oat не содержит скомпилированный код, ART запускает JIT и интерпретатор для выполнения файла .dex.
  2. JIT-компиляция включена для всех приложений, которые не были скомпилированы в соответствии с фильтром компиляции speed (который указывает "скомпилировать как можно больше кода из приложения").
  3. Данные профиля JIT сохраняются в файл в системном каталоге, доступ к которому есть только у приложения.
  4. Демон AOT-компиляции (dex2oat) анализирует этот файл, чтобы управлять компиляцией.

    Демон JIT
    Рисунок 3. действия демона JIT;

Сервис Google Play – это пример приложения, которое работает так же, как общие библиотеки.

Рабочий процесс JIT

Архитектура JIT
Рисунок 4. Поток данных JIT.
  • Информация профилирования хранится в кеше кода и удаляется при нехватке памяти.
    • Нет гарантии, что снимок, сделанный, когда приложение работало в фоновом режиме, будет содержать полные данные (то есть все, что было скомпилировано JIT-компилятором).
    • Мы не пытаемся записать все данные, поскольку это может повлиять на производительность во время выполнения.
  • Методы могут иметь три статуса:
    • интерпретируемый (DEX-код);
    • JIT-компиляция
    • Компиляция AOT
    Если существуют оба типа кода (например, из-за повторной деоптимизации), предпочтение отдается коду JIT.
  • Объем памяти, необходимый для работы JIT без ущерба для производительности активного приложения, зависит от самого приложения. Большим приложениям требуется больше памяти, чем маленьким. Как правило, для больших приложений этот показатель составляет около 4 МБ.

Как включить ведение журналов JIT

Чтобы включить ведение журнала JIT, выполните следующие команды:

adb root
adb shell stop
adb shell setprop dalvik.vm.extra-opts -verbose:jit
adb shell start

Отключить JIT

Чтобы отключить JIT, выполните следующие команды:

adb root
adb shell stop
adb shell setprop dalvik.vm.usejit false
adb shell start

Принудительная компиляция

Чтобы принудительно выполнить компиляцию, выполните следующие действия:

adb shell cmd package compile

Распространенные примеры использования принудительной компиляции определенного пакета:

  • На основе профиля:
    adb shell cmd package compile -m speed-profile -f my-package
    
  • Полное:
    adb shell cmd package compile -m speed -f my-package
    

Распространенные сценарии принудительной компиляции всех пакетов:

  • На основе профиля:
    adb shell cmd package compile -m speed-profile -f -a
    
  • Полное:
    adb shell cmd package compile -m speed -f -a
    

Как удалить данные профиля

На устройствах с Android 13 или более ранней версии

Чтобы удалить локальные данные профиля и скомпилированный код, выполните следующие действия:

adb shell pm compile --reset 

На устройствах с Android 14 или более поздней версии

Чтобы удалить только локальные данные профиля:

adb shell pm art clear-app-profiles 

Примечание. В отличие от команды для Android 13 и более ранних версий, эта команда не удаляет данные внешнего профиля (.dm), установленные вместе с приложением.

Чтобы удалить локальные данные профиля и скомпилированный код, созданный на основе этих данных (то есть вернуться к состоянию установки), выполните следующие действия:

adb shell pm compile --reset 

Примечание. Эта команда не удаляет скомпилированный код, созданный на основе внешних данных профиля (.dm), которые устанавливаются вместе с приложением.

Чтобы удалить весь скомпилированный код, выполните следующую команду:

adb shell cmd package compile -m verify -f 

Примечание. Эта команда сохраняет локальные данные профиля.