Мы настоятельно рекомендуем автоматизировать создание правил профиля с помощью библиотеки 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/**->**(**)**
Поддерживаемые типы в правилах базового профиля
Правила базового профиля поддерживают следующие типы. Подробную информацию об этих типах см. в формате Dalvik Executable (DEX) .
Характер | Тип | Описание |
---|---|---|
B | байт | Знаковый байт |
C | голец | Кодовая точка символа Юникода, закодированная в 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, библиотека загружает профиль при первом запуске вашего APK. Это может помешать процессу генерации профиля, поэтому отключите его с помощью следующей команды:
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
adb shell am broadcast -a androidx.profileinstaller.action.SKIP_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver
- Запустите приложение и вручную пройдитесь по важным пользовательским маршрутам, для которых вы хотите собрать профиль.
- Подскажите ART сбросить профили. Если ваш APK зависит от библиотеки установщика профилей Jetpack, используйте ее для дампа профилей:
Если вы не используете установщик профилей, вручную создайте дамп профилей в эмуляторе, используя следующую команду:adb shell am broadcast -a androidx.profileinstaller.action.SAVE_FILE $PACKAGE_NAME/androidx.profileinstaller.ProfileInstallReceiver adb shell am force-stop $PACKAGE_NAME
adb root adb shell killall -s SIGUSR1 $PACKAGE_NAME 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 — это интерфейс командной строки, который компилирует HRF базового профиля в скомпилированный формат. Интерфейс командной строки также поставляется в репозитории 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 | Андроид С+ | 31+ |
v0_1_0_p | Android P, Q и R | 28-30 |
v0_0_9_omr1 | Андроид О MR1 | 27 |
v0_0_5_o | Андроид О | 26 |
v0_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 содержит информацию профиля, которая передается диспетчеру пакетов на устройстве.
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}
- Зависшие частичные блокировки пробуждения