Мы настоятельно рекомендуем автоматизировать генерацию правил профиля с помощью библиотеки Jetpack Macrobenchmark, чтобы сократить ручные усилия и повысить общую масштабируемость. Тем не менее, можно вручную создавать и измерять правила профиля в вашем приложении.
Определите правила профиля вручную
Вы можете вручную определить правила профиля в приложении или модуле библиотеки, создав файл baseline-prof.txt
, расположенный в каталоге src/main
. Это та же папка, которая содержит файл AndroidManifest.xml
.
Файл определяет одно правило на строку. Каждое правило представляет собой шаблон для сопоставления методов или классов в приложении или библиотеке, которые необходимо оптимизировать.
Синтаксис этих правил является надмножеством человекочитаемого формата профиля ART (HRF) при использовании adb shell profman --dump-classes-and-methods
. Синтаксис похож на синтаксис дескрипторов и сигнатур , но позволяет использовать подстановочные знаки для упрощения процесса написания правил.
В следующем примере показано несколько правил базового профиля, включенных в библиотеку Jetpack Compose:
HSPLandroidx/compose/runtime/ComposerImpl;->updateValue(Ljava/lang/Object;)V
HSPLandroidx/compose/runtime/ComposerImpl;->updatedNodeCount(I)I
HLandroidx/compose/runtime/ComposerImpl;->validateNodeExpected()V
PLandroidx/compose/runtime/CompositionImpl;->applyChanges()V
HLandroidx/compose/runtime/ComposerKt;->findLocation(Ljava/util/List;I)I
Landroidx/compose/runtime/ComposerImpl;
Вы можете попробовать изменить правила профиля в этом примере проекта Compiler Explorer . Обратите внимание, что Compiler Explorer поддерживает только понятный человеку формат профиля ART (HRF), поэтому подстановочные знаки не поддерживаются.
Синтаксис правила
Эти правила принимают одну из двух форм, в зависимости от того, направлены ли они на методы или классы:
[FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE]
Правило класса использует следующий шаблон:
[CLASS_DESCRIPTOR]
Подробное описание смотрите в следующей таблице:
Синтаксис | Описание |
---|---|
FLAGS | Представляет один или несколько символов H , S и P указывающих, должен ли этот метод быть помечен как Hot , Startup или Post Startup в отношении типа запуска.Метод с флагом H указывает на то, что это «горячий» метод, то есть он вызывается много раз в течение жизненного цикла приложения.Метод с флагом S указывает на то, что это метод, вызываемый во время запуска.Метод с флагом P указывает, что это метод, вызываемый после запуска.Класс, присутствующий в этом файле, указывает, что он используется во время запуска и должен быть предварительно выделен в куче, чтобы избежать затрат на загрузку классов. Компилятор ART использует различные стратегии оптимизации, такие как AOT-компиляция этих методов и выполнение оптимизаций макета в сгенерированном файле AOT. |
CLASS_DESCRIPTOR | Дескриптор для класса целевого метода. Например, androidx.compose.runtime.SlotTable имеет дескриптор Landroidx/compose/runtime/SlotTable; . L добавляется здесь в соответствии с форматом исполняемого файла Dalvik (DEX) . |
METHOD_SIGNATURE | Сигнатура метода, включая имя, типы параметров и типы возвращаемых данных метода. Например:// LayoutNode.kt fun isPlaced():Boolean { // ... } в LayoutNode есть сигнатура isPlaced()Z . |
Эти шаблоны могут иметь подстановочные знаки, чтобы одно правило охватывало несколько методов или классов. Для получения руководства по написанию с синтаксисом правил в Android Studio см. плагин Android Baseline Profiles .
Пример правила подстановочных знаков может выглядеть примерно так:
HSPLandroidx/compose/ui/layout/**->**(**)**
Поддерживаемые типы в правилах базового профиля
Правила Baseline Profile поддерживают следующие типы. Подробнее об этих типах см. в формате Dalvik Executable (DEX) .
Характер | Тип | Описание |
---|---|---|
B | байт | Знаковый байт |
C | чар | Кодовая точка символа Unicode, закодированная в UTF-16 |
D | двойной | Значение с плавающей запятой двойной точности |
F | плавать | Значение с плавающей запятой одинарной точности |
I | инт | Целое число |
J | длинный | Длинное целое число |
S | короткий | Подписано коротко |
V | пустота | Пустота |
Z | булев | Правда или ложь |
L (название класса) | ссылка | Экземпляр имени класса |
Кроме того, библиотеки могут определять правила, которые упакованы в артефакты AAR. Когда вы создаете APK для включения этих артефактов, правила объединяются вместе — аналогично тому, как выполняется слияние манифестов — и компилируются в компактный бинарный профиль ART, специфичный для APK.
ART использует этот профиль, когда APK используется на устройствах для AOT-компиляции определенного подмножества приложения во время установки на Android 9 (уровень API 28) или Android 7 (уровень API 24) при использовании ProfileInstaller
.
Вручную соберите базовые профили
Вы можете вручную сгенерировать базовый профиль без настройки библиотеки Macrobenchmark и создать автоматизацию пользовательского интерфейса для критически важных пользовательских путей. Хотя мы рекомендуем использовать Macrobenchmarks, это не всегда возможно. Например, если вы используете систему сборки, отличную от Gradle, вы не можете использовать плагин Gradle Baseline Profile. В таких случаях вы можете вручную собирать правила базового профиля. Это намного проще, если вы используете устройство или эмулятор, работающий под управлением API 34 и выше. Хотя это все еще возможно с более низкими уровнями API, для этого требуется доступ root, и вам нужно использовать эмулятор, работающий под управлением образа AOSP. Вы можете собирать правила напрямую, выполнив следующие действия:
- Установите релизную версию вашего приложения на тестовое устройство. Тип сборки приложения не должен быть оптимизирован для R8 и не должен быть отлаживаемым для захвата профиля, который может использоваться системой сборки.
- Отключите установку профиля и закройте приложение. Если ваш APK имеет зависимость от библиотеки Jetpack Profile Installer , библиотека загружает профиль при первом запуске вашего APK. Это может помешать процессу генерации профиля, поэтому отключите ее с помощью следующей команды:
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE WRITE_SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
Сбросьте компиляцию приложения и очистите все профили.
API 34 и выше
adb shell cmd package compile -f -m verify $PACKAGE_NAME adb shell pm art clear-app-profiles $PACKAGE_NAME
API 33 и ниже
adb root adb shell cmd package compile --reset $PACKAGE_NAME
Запустите приложение и вручную пройдите по важным путям пользователя, для которых вы хотите собрать профиль.
Подождите не менее пяти секунд, чтобы профили стабилизировались.
Выполните действие сохранения и дождитесь завершения сохранения. Если ваш APK зависит от библиотеки Jetpack Profile Installer, используйте ее для дампа профилей:
Если вы не используете Profile Installer, вручную скопируйте профили на эмулятор с помощью следующей команды:adb shell am broadcast -a androidx.profileinstaller.action.SAVE_PROFILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver sleep 1 # wait 1 second adb shell am force-stop $PACKAGE_NAME
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME sleep 1 # wait 1 second adb shell am force-stop $PACKAGE_NAME
Преобразуйте сгенерированные двоичные профили в текст:
API 34 и выше
adb shell pm dump-profiles --dump-classes-and-methods $PACKAGE_NAME
API 33 и ниже
Определите, был ли создан ссылочный профиль или текущий профиль. Ссылочный профиль находится в следующем месте: Текущий профиль находится по следующему адресу:/data/misc/profiles/ref/$$PACKAGE_NAME/primary.prof
Определите местоположение APK:/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Выполним преобразование:adb root adb shell pm path $PACKAGE_NAME
adb root adb shell profman --dump-classes-and-methods --profile-file=$PROFILE_PATH --apk=$APK_PATH > /data/misc/profman/$PACKAGE_NAME-primary.prof.txt
Используйте
adb
для извлечения сброшенного профиля с устройства:adb pull /data/misc/profman/$PACKAGE_NAME-primary.prof.txt PATH_TO_APP_MODULE/src/main/
Это извлекает сгенерированные правила профиля и устанавливает их в ваш модуль приложения. В следующий раз, когда вы построите приложение, базовый профиль будет включен. Проверьте это, выполнив шаги в разделе Проблемы установки .
Измерение улучшений приложения вручную
Мы настоятельно рекомендуем вам измерять улучшения приложения с помощью бенчмаркинга. Однако, если вы хотите измерить улучшения вручную, вы можете начать с измерения неоптимизированного запуска приложения для справки.
PACKAGE_NAME=com.example.app
# Force Stop App adb shell am force-stop $PACKAGE_NAME # Reset compiled state adb shell cmd package compile --reset $PACKAGE_NAME
# Measure App startup # This corresponds to `Time to initial display` metric. adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Далее загрузите базовый профиль.
# Unzip the Release APK first. unzip release.apk
# Create a ZIP archive. # The name should match the name of the APK. # Copy `baseline.prof{m}` and rename it `primary.prof{m}`. cp assets/dexopt/baseline.prof primary.prof cp assets/dexopt/baseline.profm primary.profm
# Create an archive. zip -r release.dm primary.prof primary.profm
# Confirm that release.dm only contains the two profile files: unzip -l release.dm # Archive: release.dm # Length Date Time Name # --------- ---------- ----- ---- # 3885 1980-12-31 17:01 primary.prof # 1024 1980-12-31 17:01 primary.profm # --------- ------- # 2 files
# Install APK + Profile together. adb install-multiple release.apk release.dm
Чтобы убедиться, что пакет был оптимизирован при установке, выполните следующую команду:
# Check dexopt state.
adb shell dumpsys package dexopt | grep -A 1 $PACKAGE_NAME
Вывод должен содержать информацию о том, что пакет скомпилирован:
[com.example.app]
path: /data/app/~~YvNxUxuP2e5xA6EGtM5i9A==/com.example.app-zQ0tkJN8tDrEZXTlrDUSBg==/base.apk
arm64: [status=speed-profile] [reason=install-dm]
Теперь вы можете измерить производительность запуска приложения, как и раньше, но без сброса скомпилированного состояния. Убедитесь, что вы не сбросили скомпилированное состояние для пакета.
# Force stop app adb shell am force-stop $PACKAGE_NAME
# Measure app startup adb shell am start-activity -W -n $PACKAGE_NAME/.ExampleActivity \ | grep "TotalTime"
Базовые профили и профген
В этом разделе описывается, что делает инструмент profgen при создании компактной двоичной версии базового профиля .
Profgen-cli помогает в компиляции профилей, интроспекции и транспиляции профилей ART, поэтому их можно устанавливать на устройствах на базе Android независимо от целевой версии SDK.
Profgen-cli — это CLI, который компилирует HRF базового профиля в его скомпилированный формат. CLI также поставляется в репозитории cmdline-tools
как часть Android SDK.
Эти функции доступны в ветке studio-main
:
➜ ../cmdline-tools/latest/bin
apkanalyzer
avdmanager
lint
profgen
retrace
screenshot2
sdkmanager
Создавайте компактные бинарные профили с помощью Profgen-cli
Команды, доступные с Profgen-cli, это bin
, validate
и dumpProfile
. Чтобы увидеть доступные команды, используйте profgen --help
:
➜ profgen --help
Usage: profgen options_list
Subcommands:
bin - Generate Binary Profile
validate - Validate Profile
dumpProfile - Dump a binary profile to a HRF
Options:
--help, -h -> Usage info
Используйте команду bin
для генерации компактного бинарного профиля. Ниже приведен пример вызова:
profgen bin ./baseline-prof.txt \
--apk ./release.apk \
--map ./obfuscation-map.txt \
--profile-format v0_1_0_p \
--output ./baseline.prof \
Чтобы увидеть доступные параметры, используйте profgen bin options_list
:
Usage: profgen bin options_list
Arguments:
profile -> File path to Human Readable profile { String }
Options:
--apk, -a -> File path to apk (always required) { String }
--output, -o -> File path to generated binary profile (always required)
--map, -m -> File path to name obfuscation map { String }
--output-meta, -om -> File path to generated metadata output { String }
--profile-format, -pf [V0_1_0_P] -> The ART profile format version
{ Value should be one of [
v0_1_5_s, v0_1_0_p, v0_0_9_omr1, v0_0_5_o, v0_0_1_n
]
}
--help, -h -> Usage info
Первый аргумент представляет собой путь к HRF-файлу baseline-prof.txt
.
Profgen-cli также нужен путь к релизной сборке APK и карта обфускации , которая используется для обфускации APK при использовании R8 или Proguard. Таким образом, profgen
может преобразовать исходные символы в HRF в их соответствующие обфусцированные имена при построении скомпилированного профиля.
Поскольку форматы профилей ART несовместимы ни вперед, ни назад, предоставьте формат профиля, чтобы profgen
упаковывал метаданные профиля ( profm
), которые можно использовать для перекодирования одного формата профиля ART в другой при необходимости.
Форматы профилей и версии платформы
При выборе формата профиля доступны следующие параметры:
Формат профиля | Версия платформы | уровень API |
---|---|---|
v0_1_5_s | Android S+ | 31+ |
v0_1_0_p | Android P, Q и R | 28-30 |
v0_0_9_omr1 | Android OMR1 | 27 |
в0_0_5_о | Андроид О | 26 |
в0_0_1_н | Андроид N | 24-25 |
Скопируйте выходные файлы baseline.prof
и baseline.profm
в папку assets
или dexopt
в APK.
Карты запутывания
Вам нужно предоставить карту обфускации только в том случае, если HRF использует исходные символы. Если HRF сгенерирован из сборки релиза, которая уже обфусцирована, и нет необходимости в отображении, вы можете проигнорировать эту опцию и скопировать выходные данные в папку assets
или dexopt
.
Традиционная установка базовых профилей
Базовые профили традиционно доставляются на устройство одним из двух способов.
Используйте install-multiple
с DexMetadata
На устройствах с API 28 и более поздними версиями клиент Play загружает полезную нагрузку APK и DexMetadata (DM) для устанавливаемой версии APK. DM содержит информацию профиля, которая передается в Package Manager на устройстве.
APK и DM устанавливаются как часть одного сеанса установки с помощью чего-то вроде:
adb install-multiple base.apk base.dm
Установщик профиля Jetpack
На устройствах с API уровня 29 и выше библиотека Jetpack ProfileInstaller предоставляет альтернативный механизм для установки профиля, упакованного в assets
или dexopt
после установки APK на устройство. ProfileInstaller
вызывается ProfileInstallReceiver
или приложением напрямую.
Библиотека ProfileInstaller перекодирует профиль на основе версии SDK целевого устройства и копирует профиль в каталог cur
на устройстве (специфичный для пакета промежуточный каталог для профилей ART на устройстве).
Когда устройство находится в режиме ожидания, профиль подхватывается процессом bg-dexopt
на устройстве.
Боковая загрузка базового профиля
В этом разделе описывается, как установить базовый профиль с помощью APK.
Трансляция с androidx.profileinstaller
На устройствах с API 24 и более поздними версиями можно передать команду на установку профиля:
# Broadcast the install profile command - moves binary profile from assets
# to a location where ART uses it for the next compile.
# When successful, the following command prints "1":
adb shell am broadcast \
-a androidx.profileinstaller.action.INSTALL_PROFILE \
<pkg>/androidx.profileinstaller.ProfileInstallReceiver
# Kill the process
am force-stop <pkg>
# Compile the package based on profile
adb shell cmd package compile -f -m speed-profile <pkg>
ProfileInstaller отсутствует в большинстве APK с базовыми профилями (которые есть примерно в 77 тыс. из 450 тыс. приложений в Play), хотя он присутствует фактически в каждом APK, использующем Compose. Это связано с тем, что библиотеки могут предоставлять профили без объявления зависимости от ProfileInstaller. Добавление зависимости в каждую библиотеку с профилем применяется, начиная с Jetpack.
Используйте install-multiple
с profgen или DexMetaData
На устройствах с API 28 и более поздними версиями можно загрузить базовый профиль без необходимости установки библиотеки ProfileInstaller в приложение.
Для этого используйте Profgen-cli:
profgen extractProfile \
--apk app-release.apk \
--output-dex-metadata app-release.dm \
--profile-format V0_1_5_S # Select based on device and the preceding table.
# Install APK and the profile together
adb install-multiple appname-release.apk appname-release.dm
Для поддержки разделения APK выполните предыдущие шаги по извлечению профиля один раз для каждого APK. Во время установки передайте каждый APK и связанный с ним файл .dm
, убедившись, что имена APK и .dm
совпадают:
adb install-multiple appname-base.apk appname-base.dm \
appname-split1.apk appname-split1.dm
Проверка
Чтобы проверить правильность установки профиля, можно воспользоваться шагами из раздела Измерение улучшений приложения вручную .
Сбросить содержимое бинарного профиля
Для анализа содержимого компактной двоичной версии базового профиля используйте опцию Profgen-cli dumpProfile
:
Usage: profgen dumpProfile options_list
Options:
--profile, -p -> File path to the binary profile (always required)
--apk, -a -> File path to apk (always required) { String }
--map, -m -> File path to name obfuscation map { String }
--strict, -s [true] -> Strict mode
--output, -o -> File path for the HRF (always required) { String }
--help, -h -> Usage info
dumpProfile
необходим APK, поскольку компактное двоичное представление хранит только смещения DEX и, следовательно, они необходимы ему для восстановления имен классов и методов.
Строгий режим включен по умолчанию, и он выполняет проверку совместимости профиля с файлами DEX в APK. Если вы пытаетесь отладить профили, созданные другим инструментом, вы можете получить сбои совместимости, которые не позволят вам сделать дамп для исследования. В таких случаях вы можете отключить строгий режим с помощью --strict false
. Однако в большинстве случаев вам следует оставить строгий режим включенным.
Карта обфускации необязательна; если она указана, она помогает преобразовать запутанные символы в их понятные человеку версии для удобства использования.
{% дословно %}Рекомендовано для вас
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Лучшие практики для повышения производительности SQLite
- Базовые профили {:#baseline-profiles}
- Застрявшие частичные блокировки пробуждения