Настройка АРТ

На этой странице обсуждается, как настроить ART и параметры его компиляции. Темы, затронутые здесь, включают настройку предварительной компиляции образа системы, параметры компиляции dex2oat и то, как найти компромисс между пространством системного раздела, пространством раздела данных и производительностью.

См. ART и Dalvik , формат исполняемого файла Dalvik и остальные страницы на сайте source.android.com для работы с ART. См. Проверка поведения приложения в среде выполнения Android (ART) , чтобы убедиться, что ваши приложения работают правильно.

Как работает АРТ

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

  1. Приложение изначально устанавливается без какой-либо компиляции AOT. Первые несколько раз приложение будет интерпретировано, а часто выполняемые методы будут JIT-компилированы.
  2. Когда устройство простаивает и заряжается, демон компиляции запускается для AOT-компиляции часто используемого кода на основе профиля, созданного во время первых запусков.
  3. При следующем перезапуске приложения будет использоваться код, ориентированный на профиль, и не будет выполняться JIT-компиляция во время выполнения для уже скомпилированных методов. Методы, которые компилируются JIT во время новых запусков, будут добавлены в профиль, который затем будет выбран демоном компиляции.

ART включает в себя компилятор (инструмент dex2oat ) и среду выполнения ( libart.so ), которая загружается для запуска Zygote. Инструмент dex2oat берет файл APK и создает один или несколько файлов артефактов компиляции, которые загружает среда выполнения. Количество файлов, их расширения и имена могут меняться в разных версиях, но начиная с версии Android O генерируются следующие файлы:

  • .vdex : содержит несжатый код DEX APK с некоторыми дополнительными метаданными для ускорения проверки.
  • .odex : содержит скомпилированный код AOT для методов в APK.
  • .art (optional) : содержит внутренние представления ART некоторых строк и классов, перечисленных в APK, которые используются для ускорения запуска приложения.

Варианты компиляции

Варианты компиляции для ART бывают двух категорий:

  1. Конфигурация системного ПЗУ: какой код компилируется с помощью AOT при создании образа системы.
  2. Конфигурация среды выполнения: как ART компилирует и запускает приложения на устройстве.

Одной из основных опций ART для настройки этих двух категорий являются фильтры компилятора . Фильтры компилятора управляют тем, как ART компилирует код DEX, и являются опцией, передаваемой инструменту dex2oat . Начиная с Android O, официально поддерживаются четыре фильтра:

  • Verify : запускать только проверку кода DEX.
  • quicken : запустите проверку кода DEX и оптимизируйте некоторые инструкции DEX, чтобы повысить производительность интерпретатора.
  • скорость : запустить проверку кода DEX и AOT-компилировать все методы.
  • speed-profile : запустить проверку кода DEX и методы компиляции AOT, перечисленные в файле профиля.

Конфигурация системного ПЗУ

Существует несколько вариантов сборки ART для настройки системного ПЗУ. Способ настройки этих параметров зависит от доступного места для хранения /system и количества предустановленных приложений. Файлы JAR/APK, скомпилированные в системное ПЗУ, можно разделить на четыре категории:

  • Код загрузочного пути к классам: по умолчанию скомпилирован с фильтром компилятора скорости .
  • Код системного сервера: по умолчанию скомпилирован с фильтром компилятора скорости .
  • Основные приложения для конкретных продуктов: по умолчанию скомпилированы с фильтром компилятора скорости .
  • Все остальные приложения: скомпилированы с фильтром quicken по умолчанию.

Параметры Makefile

  • WITH_DEXPREOPT
  • Вызывается ли dex2oat для кода DEX, установленного в образе системы. Включено по умолчанию.

  • DONT_DEXPREOPT_PREBUILTS (начиная с Android L)
  • Включение DONT_DEXPREOPT_PREBUILTS предотвращает предварительную оптимизацию предварительных сборок. Это приложения, include $(BUILD_PREBUILT) , указанные в файле Android.mk , например Gmail. Пропуск предварительной оптимизации готовых приложений, которые, скорее всего, будут обновляться через Google Play, экономит /system пространство, но увеличивает время первой загрузки.

  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER (начиная с Android 9)
  • PRODUCT_DEX_PREOPT_DEFAULT_COMPILER_FILTER указывает фильтр компилятора по умолчанию для предварительно оптимизированных приложений. Это приложения, include $(BUILD_PREBUILT) , указанные в файле Android.mk , например Gmail. Если не указано, значение по умолчанию — quicken.

  • WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY (новое в Android O MR1)
  • Включение WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY предварительно оптимизирует только путь к классам загрузки и jar-файлы системного сервера.

  • LOCAL_DEX_PREOPT
  • Предварительную оптимизацию также можно включить или отключить для отдельного приложения, указав параметр LOCAL_DEX_PREOPT в определении модуля. Это может быть полезно для отключения предварительной оптимизации приложений, которые могут немедленно получать обновления Google Play, поскольку обновления сделают предварительно оптимизированный код в образе системы устаревшим. Это также полезно для экономии места при OTA обновления основных версий, поскольку у пользователей могут уже быть более новые версии приложений в разделе данных.

    LOCAL_DEX_PREOPT поддерживает значения «true» или «false» для включения или отключения предварительной оптимизации соответственно. Кроме того, можно указать «nostripping», если предварительная оптимизация не должна удалять файл classes.dex из файла APK или JAR. Обычно этот файл удаляется, так как он больше не нужен после предварительной оптимизации, но этот последний параметр необходим, чтобы сторонние подписи APK оставались действительными.

  • PRODUCT_DEX_PREOPT_BOOT_FLAGS
  • Передает параметры dex2oat для управления компиляцией загрузочного образа. Его можно использовать для указания настраиваемых списков классов изображений, скомпилированных списков классов и фильтров компилятора.

  • PRODUCT_DEX_PREOPT_DEFAULT_FLAGS
  • Передает параметры dex2oat для управления тем, как компилируется все, кроме загрузочного образа.

  • PRODUCT_DEX_PREOPT_MODULE_CONFIGS
  • Предоставляет возможность передавать параметры dex2oat для определенного модуля и конфигурации продукта. Он устанавливается в файле device.mk продукта с помощью $(call add-product-dex-preopt-module-config,<modules>,<option>) где <modules> — это список имен LOCAL_MODULE и LOCAL_PACKAGE для JAR и APK. файлов соответственно.

  • PRODUCT_DEXPREOPT_SPEED_APPS (New in Android O)
  • Список приложений, которые были определены как основные для продуктов и которые желательно компилировать с помощью фильтра компилятора скорости . Например, постоянные приложения, такие как SystemUI, получают возможность использовать компиляцию на основе профиля только при следующей перезагрузке, поэтому для продукта может быть лучше, чтобы эти приложения всегда компилировались с помощью AOT.

  • PRODUCT_SYSTEM_SERVER_APPS (New in Android O)
  • Список приложений, загружаемых системным сервером. Эти приложения будут скомпилированы по умолчанию с фильтром компилятора скорости .

  • PRODUCT_ART_TARGET_INCLUDE_DEBUG_BUILD(Post Android O)
  • Включать ли отладочную версию ART на устройство. По умолчанию это включено для сборок userdebug и eng. Поведение можно переопределить, явно установив для параметра значение true или false .

    По умолчанию устройство будет использовать версию без отладки ( libart.so ). Для переключения установите для системного свойства persist.sys.dalvik.vm.lib.2 значение libartd.so .

  • WITH_DEXPREOPT_PIC (Removed in Android O)
  • В Android 5.1.0–Android 6.0.1 можно указать WITH_DEXPREOPT_PIC , чтобы включить позиционно-независимый код (PIC). При этом скомпилированный код из образа не нужно перемещать из /system в /data/dalvik-cache, что экономит место в разделе данных. Однако это оказывает небольшое влияние на время выполнения, поскольку отключает оптимизацию, использующую код, зависящий от позиции. Как правило, устройства, желающие сэкономить место в /data, должны включить компиляцию PIC.

    В Android 7.0 компиляция PIC была включена по умолчанию.

  • WITH_DEXPREOPT_BOOT_IMG_ONLY (удалено в Android O MR1)
  • Этот параметр был заменен на WITH_DEXPREOPT_BOOT_IMG_AND_SYSTEM_SERVER_ONLY, который также использует файлы jar системного сервера.

Конфигурация пути к классам загрузки

  • Список предварительно загруженных классов
  • Список предварительно загруженных классов — это список классов, которые зигота инициализирует при запуске. Это избавляет каждое приложение от необходимости запускать эти инициализаторы классов по отдельности, позволяя им запускаться быстрее и совместно использовать страницы в памяти. Файл со списком предварительно загруженных классов по умолчанию находится в frameworks/base/config/preloaded-classes и содержит список, настроенный для типичного использования телефона. Это может отличаться для других устройств, таких как носимые устройства, и должно быть соответствующим образом настроено. Будьте осторожны при настройке; добавление слишком большого количества классов тратит память впустую, когда загружаются неиспользуемые классы. Добавление слишком малого количества классов вынуждает каждое приложение иметь собственную копию, что опять же приводит к трате памяти.

    Пример использования (в файле device.mk продукта):

    PRODUCT_COPY_FILES += <filename>:system/etc/preloaded-classes
    

    Примечание. Эта строка должна быть размещена до наследования любых make-файлов конфигурации продукта, которые получают файл по умолчанию из: build/target/product/base.mk

  • Список классов изображений
  • Список классов изображений — это список классов, которые dex2oat инициализирует заранее и сохраняет в файле boot.art. Это позволяет zygote загружать эти результаты из файла boot.art при запуске вместо того, чтобы запускать инициализаторы для этих классов во время предварительной загрузки. Ключевой особенностью этого является то, что страницы, загруженные из образа и совместно используемые между процессами, могут быть чистыми, что позволяет легко заменять их в ситуациях с нехваткой памяти. В L по умолчанию список классов изображений использует тот же список, что и список предварительно загруженных классов. Начиная с post-L в AOSP, пользовательский список классов изображений можно указать, используя:

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    Пример использования (в device.mk продукта):

    PRODUCT_DEX_PREOPT_BOOT_FLAGS += --image-classes=<filename>
    
  • Список скомпилированных классов
  • В post-L AOSP можно указать подмножество классов из загрузочного пути к классам для компиляции во время предварительной оптимизации с использованием списка скомпилированных классов. Это может быть полезно для устройств, которые очень ограничены в пространстве и не могут вместить весь предварительно оптимизированный загрузочный образ. Однако классы заметок, не указанные в этом списке, не будут скомпилированы — даже на устройстве — и должны быть интерпретированы, что может повлиять на производительность во время выполнения. По умолчанию dex2oat будет искать список скомпилированных классов в $OUT/system/etc/compiled-classes, поэтому пользовательский может быть скопирован в это место с помощью device.mk. Конкретное местоположение файла также можно указать с помощью:

    PRODUCT_DEX_PREOPT_BOOT_FLAGS
    

    Пример использования (в device.mk продукта):

    PRODUCT_COPY_FILES += <filename>:system/etc/compiled-classes
    

    Примечание. Эта строка должна быть размещена до наследования любых make-файлов конфигурации продукта, которые получают файл по умолчанию из: build/target/product/base.mk

Конфигурация среды выполнения

Параметры JIT

Следующие параметры влияют на выпуски Android только в том случае, если доступен компилятор ART JIT.

  • dalvik.vm.usejit: включен ли JIT.
  • dalvik.vm.jitinitialsize (по умолчанию 64 КБ): начальная емкость кэша кода. Кэш кода регулярно GC и увеличивается при необходимости.
  • dalvik.vm.jitmaxsize (по умолчанию 64M): максимальная емкость кэша кода.
  • dalvik.vm.jitthreshold: (по умолчанию 10000) — это порог, который должен пройти счетчик «горячости» метода, чтобы метод был скомпилирован JIT. Счетчик «горячости» — это внутренняя метрика среды выполнения. Он включает в себя количество вызовов, обратных ответвлений и другие факторы.
  • dalvik.vm.usejitprofiles: включены ли профили JIT; это можно использовать, даже если dalvik.vm.usejit имеет значение false. Обратите внимание, что если это значение равно false, профиль скорости фильтра компилятора не выполняет AOT-компиляцию какого-либо метода и эквивалентен quicken .
  • dalvik.vm.jitprithreadweight (по умолчанию dalvik.vm.jitthreshold / 20) — вес «выборок» JIT (см. jitthreshold) для потока пользовательского интерфейса приложения. Используйте для ускорения компиляции методов, которые напрямую влияют на взаимодействие пользователей с приложением.
  • dalvik.vm.jittransitionweight: (по умолчанию dalvik.vm.jitthreshold / 10) вес вызова метода, который переходит между компилируемым кодом и интерпретатором. Это помогает убедиться, что задействованные методы скомпилированы для минимизации переходов (которые являются дорогостоящими).

Опции менеджера пакетов

Начиная с Android 7.0, существует общий способ указать уровень компиляции/проверки, который происходит на разных этапах. Уровни компиляции можно настроить с помощью системных свойств со значениями по умолчанию:

  • pm.dexopt.install=speed-profile
  • Это фильтр компиляции, используемый при установке приложений через Google Play. Мы рекомендуем установить фильтр установки на профиль скорости, чтобы разрешить использование профилей из файлов метаданных dex. Обратите внимание, что если профиль не указан или если он пуст, профиль скорости эквивалентен ускорению.

  • pm.dexopt.bg-dexopt=speed-profile
  • Это фильтр компиляции, используемый, когда устройство находится в режиме ожидания, заряжается и полностью заряжено. Попробуйте фильтр компилятора профиля скорости, чтобы воспользоваться преимуществами компиляции на основе профиля и сэкономить место в хранилище.

  • pm.dexopt.boot=verify
  • Фильтр компиляции, используемый после беспроводного обновления. Мы настоятельно рекомендуем проверить фильтр компилятора для этой опции, чтобы избежать очень долгого времени загрузки.

  • pm.dexopt.first-boot=quicken
  • Фильтр компиляции при первой загрузке устройства. Используемый здесь фильтр повлияет только на время загрузки после заводских настроек. Мы рекомендуем ускорить фильтр, чтобы избежать долгого времени, прежде чем пользователь сможет использовать телефон в первый раз. Обратите внимание, что если все приложения в /system уже скомпилированы с фильтром компилятора quicken или скомпилированы с фильтром компилятора speed или speed-profile , pm.dexopt.first-boot не действует.

Опции Dex2oat

Обратите внимание, что эти параметры влияют на dex2oat во время компиляции на устройстве, а также во время предварительной оптимизации, в то время как большинство обсуждавшихся выше параметров влияют только на предварительную оптимизацию.

Чтобы управлять dex2oat во время компиляции загрузочного образа:

  • dalvik.vm.image-dex2oat-Xms: начальный размер кучи
  • dalvik.vm.image-dex2oat-Xmx: максимальный размер кучи
  • dalvik.vm.image-dex2oat-filter: параметр фильтра компилятора
  • dalvik.vm.image-dex2oat-threads: количество используемых потоков

Чтобы управлять dex2oat во время компиляции всего, кроме загрузочного образа:

  • dalvik.vm.dex2oat-Xms: начальный размер кучи
  • dalvik.vm.dex2oat-Xmx: максимальный размер кучи
  • dalvik.vm.dex2oat-filter: параметр фильтра компилятора

В релизах через Android 6.0 предусмотрена одна дополнительная опция для компиляции всего, кроме загрузочного образа:

  • dalvik.vm.dex2oat-threads: количество используемых потоков

Начиная с Android 6.1 это становится двумя дополнительными вариантами компиляции всего, кроме загрузочного образа:

  • dalvik.vm.boot-dex2oat-threads: количество потоков, используемых во время загрузки
  • dalvik.vm.dex2oat-threads: количество потоков, используемых после загрузки

Начиная с Android 7.1, предусмотрено два варианта управления использованием памяти при компиляции всего, кроме загрузочного образа:

  • dalvik.vm.dex2oat-very-large: минимальный общий размер файла dex в байтах для отключения компиляции AOT
  • dalvik.vm.dex2oat-swap: использовать файл подкачки dex2oat (для устройств с малым объемом памяти)

Параметры, управляющие начальным и максимальным размером кучи для dex2oat , не следует уменьшать, поскольку они могут ограничивать набор приложений, которые можно компилировать.

Начиная с Android 11, предоставляются три параметра привязки ЦП, позволяющие ограничить потоки компилятора определенной группой ЦП:

  • dalvik.vm.boot-dex2oat-cpu-set: процессоры, выполняющие потоки dex2oat во время загрузки
  • dalvik.vm.image-dex2oat-cpu-set: Процессоры, работающие с dex2oat во время компиляции загрузочного образа
  • dalvik.vm.dex2oat-cpu-set: процессоры, выполняющие потоки dex2oat после загрузки

ЦП следует указывать в виде списка идентификаторов ЦП, разделенных запятыми. Например, чтобы запустить dex2oat на процессорах 0-3, установите:

dalvik.vm.dex2oat-cpu-set=0,1,2,3

При настройке свойств привязки ЦП мы рекомендуем сопоставить соответствующее свойство для количества потоков dex2oat, чтобы оно соответствовало количеству выбранных ЦП, чтобы избежать ненужной конкуренции за память и ввод-вывод:

dalvik.vm.dex2oat-cpu-set=0,1,2,3
dalvik.vm.dex2oat-threads=4

Начиная с Android 12 были добавлены следующие параметры:

  • dalvik.vm.ps-min-first-save-ms: время ожидания, пока среда выполнения сгенерирует профиль приложения при первом запуске приложения.
  • dalvik.vm.ps-min-save-period-ms: минимальное время ожидания перед обновлением профиля приложения.
  • dalvik.vm.systemservercompilerfilter: фильтр компилятора, который устройство будет использовать при перекомпиляции системного сервера.

Конфигурация A/B

конфигурация ПЗУ

Начиная с Android 7.0, устройства могут использовать два системных раздела для включения системных обновлений A/B . Чтобы сэкономить размер системного раздела, предварительно выбранные файлы можно установить в неиспользуемый второй системный раздел. Затем они копируются в раздел данных при первой загрузке.

Пример использования (в device-common.mk ):

PRODUCT_PACKAGES += \
     cppreopts.sh
PRODUCT_PROPERTY_OVERRIDES += \
     ro.cp_system_other_odex=1

И в BoardConfig.mk устройства:

BOARD_USES_SYSTEM_OTHER_ODEX := true

Обратите внимание, что загрузочный код пути к классам, код системного сервера и базовые приложения для конкретных продуктов всегда компилируются в системный раздел. По умолчанию все остальные приложения компилируются во второй неиспользуемый системный раздел. Это можно контролировать с помощью SYSTEM_OTHER_ODEX_FILTER , значение которого по умолчанию равно:

SYSTEM_OTHER_ODEX_FILTER ?= app/% priv-app/%

Фон dexopt OTA

На устройствах с поддержкой A/B приложения могут быть скомпилированы в фоновом режиме для обновления до нового образа системы. См. Компиляцию приложения в фоновом режиме , чтобы дополнительно включить сценарий компиляции и двоичные файлы в образ системы. Фильтр компиляции, используемый для этой компиляции, управляется с помощью:

pm.dexopt.ab-ota=speed-profile

Мы рекомендуем использовать speed-profile , чтобы воспользоваться компиляцией по профилю и сэкономить место в хранилище.