Мы настоятельно рекомендуем автоматизировать генерацию правил профилирования с помощью библиотеки 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.ktfun isPlaced():Boolean {// ...}У узла LayoutNode есть сигнатура isPlaced()Z . |
В этих шаблонах можно использовать подстановочные знаки, чтобы одно правило охватывало несколько методов или классов. Для получения пошаговых инструкций по написанию правил в Android Studio см. плагин Android Baseline Profiles .
Пример правила с использованием подстановочного знака может выглядеть примерно так:
HSPLandroidx/compose/ui/layout/**->**(**)**
Поддерживаемые типы в правилах базового профиля
Правила базового профиля поддерживают следующие типы. Подробную информацию об этих типах см. в формате исполняемого файла Dalvik (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, то вы не сможете использовать плагин Baseline Profile Gradle. В таких случаях вы можете вручную собрать правила базового профиля. Это намного проще, если вы используете устройство или эмулятор с 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 — это интерфейс командной строки, который компилирует 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 | 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 .
Традиционная установка базовых профилей
Традиционно базовые профили передаются на устройство одним из двух способов.
Используйте install-multiple с DexMetadata
На устройствах с API 28 и более поздними версиями клиент Play загружает APK-файл и полезную нагрузку DexMetadata (DM) для устанавливаемой версии APK. DM содержит информацию профиля, которая передается менеджеру пакетов на устройстве.
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 , выполняемым на устройстве.
Загрузка базового профиля
В этом разделе описывается, как установить базовый профиль, используя 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 приложений в Play Store), хотя он присутствует практически в каждом 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
Проверка
Чтобы убедиться в правильности установки профиля, вы можете воспользоваться инструкциями из раздела «Измерение улучшений приложения вручную» .
Выгрузить содержимое бинарного профиля
Для анализа содержимого компактной бинарной версии базового профиля используйте опцию dumpProfile команды Profgen-cli:
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 . Однако в большинстве случаев следует оставлять строгий режим включенным.
Карта обфускации является необязательной; если она предоставлена, она помогает преобразовать обфусцированные символы в их удобочитаемые версии для удобства использования.
{% verbatim %}Рекомендуем вам
- Примечание: текст ссылки отображается, когда JavaScript отключен.
- Рекомендации по повышению производительности SQLite.
- Базовые профили {:#baseline-profiles}
- Залипание частичной блокировки пробуждения