Чтобы сократить объем работы вручную и повысить общую масштабируемость, мы настоятельно рекомендуем автоматизировать создание правил профиля с помощью библиотеки 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 добавляется в соответствии с форматом DEX. |
METHOD_SIGNATURE |
Сигнатура метода, включая название, типы параметров и типы возвращаемых значений метода. Пример:// LayoutNode.kt fun isPlaced():Boolean { // ...} on LayoutNode имеет подпись isPlaced()Z. |
В шаблонах можно использовать подстановочные знаки, чтобы одно правило охватывало несколько методов или классов. Чтобы получить помощь по синтаксису правил в Android Studio, воспользуйтесь плагином Android Baseline Profiles.
Пример правила с подстановочным знаком:
HSPLandroidx/compose/ui/layout/**->**(**)**
Поддерживаемые типы в правилах профиля базовой конфигурации
Правила профиля Baseline поддерживают следующие типы. Подробнее о формате Dalvik Executable (DEX)…
| Персонаж | Тип | Описание |
|---|---|---|
B |
байт | Байт со знаком |
C |
char | Кодовая точка символа Unicode в кодировке UTF-16. |
D |
двойной | Число с плавающей запятой двойной точности |
F |
float | Значение с плавающей запятой одинарной точности |
I |
ПРХВ | Целое число |
J |
long | Длинное целое число |
S |
короткое видео | Короткое видео с сурдопереводом |
V |
void | Аннулировано |
Z |
Логическое значение | Верно или неверно? |
L (название курса) |
ссылка : упоминание : [*] | Экземпляр названия класса |
Кроме того, библиотеки могут определять правила, упакованные в артефакты AAR. При создании APK-файла, включающего эти артефакты, правила объединяются (подобно тому, как объединяются манифесты) и компилируются в компактный двоичный профиль ART, специфичный для APK.
ART использует этот профиль, когда APK устанавливается на устройствах с Android 9 (уровень API 28) или Android 7 (уровень API 24) при использовании ProfileInstaller, чтобы выполнить AOT-компиляцию определенного подмножества приложения.
Как вручную собрать профили базовой конфигурации
Вы можете вручную создать базовый профиль, не настраивая библиотеку Macrobenchmark, и создать автоматизацию пользовательского интерфейса для критических путей пользователей. Хотя мы рекомендуем использовать Macrobenchmark, это не всегда возможно. Например, если вы используете систему сборки, отличную от Gradle, вы не сможете использовать плагин Baseline Profile Gradle. В таких случаях вы можете вручную собрать правила профиля Baseline. Это намного проще сделать, если вы используете устройство или эмулятор с 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
Текущий профиль находится в следующем расположении:
/data/misc/profiles/cur/0/$PACKAGE_NAME/primary.prof
Определите местоположение APK-файла:
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"
Профили Baseline и profgen
В этом разделе описывается, что делает инструмент profgen при создании компактной двоичной версии базового профиля.
Profgen-cli помогает компилировать, анализировать и транспилировать профили ART, чтобы их можно было устанавливать на устройства Android независимо от целевой версии SDK.
Profgen-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
Первый аргумент – путь к файлу baseline-prof.txt в формате HRF.
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 O MR1 | 27 |
| v0_0_5_o | Android O | 26 |
| v0_0_1_n | Android N | 24-25 |
Скопируйте выходные файлы baseline.prof и baseline.profm в папку assets или dexopt в APK.
Файлы сопоставления обфускации
Файл сопоставления обфускации требуется, только если в HRF используются исходные символы. Если HRF-файл создан на основе конечной сборки, которая уже обфусцирована, и сопоставление не требуется, вы можете проигнорировать этот параметр и скопировать выходные данные в папку assets или dexopt.
Традиционная установка профилей базовой конфигурации
Обычно профили Baseline доставляются на устройство одним из двух способов.
Используйте install-multiple с DexMetadata
На устройствах с API 28 и более поздних версий клиент Google Play скачивает APK и полезную нагрузку DexMetadata (DM) для устанавливаемой версии APK. DM содержит информацию профиля, которая передается в Package Manager на устройстве.
APK и DM устанавливаются в рамках одного сеанса установки с помощью команды, похожей на следующую:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
На устройствах с уровнем API 29 и выше библиотека Jetpack ProfileInstaller предоставляет альтернативный механизм установки профиля, упакованного в assets или dexopt, после установки APK на устройство. ProfileInstaller вызывается ProfileInstallReceiver или напрямую приложением.
Библиотека ProfileInstaller перекодирует профиль в зависимости от версии SDK целевого устройства и копирует его в каталог cur (промежуточный каталог для профилей ART на устройстве).
Когда устройство бездействует, профиль выбирается процессом bg-dexopt на устройстве.
Как загрузить профиль базовой конфигурации
В этом разделе описывается, как установить профиль Baseline Profile для 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 000 из 450 000 приложений в Google 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, убедившись, что их
.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}
- Зависшие частичные запреты блокировки