我们强烈建议利用 Jetpack Macrobenchmark 库来实现配置文件规则的自动生成,以减少手动工作并提高一般可伸缩性。不过,您可以在您的应用中手动创建和衡量配置文件规则。
手动定义配置文件规则
您可以在应用中或在库模块中手动定义配置文件规则,方法是在 src/main
目录中创建一个名为 baseline-prof.txt
的文件。这是包含 AndroidManifest.xml
文件的同一个文件夹。
该文件中的每行指定了一条规则。每条规则均表示一种模式,用于匹配应用或库中需要优化的方法或类。
这些规则的语法是使用 adb shell profman --dump-classes-and-methods
时所用的人类可读懂的 ART 配置文件格式 (HRF) 的超集。该语法与描述符和签名的语法相似,但允许使用通配符以简化规则编写过程。
以下示例展示了 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;
规则语法
这些规则采用两种形式,一种用于方法,一种用于类:
[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; 。根据 Dalvik 可执行文件 (DEX) 格式,描述符中附加了 L。 |
METHOD_SIGNATURE |
方法的签名,包括方法的名称、参数类型和返回值类型。例如:LayoutNode 上的// LayoutNode.kt fun isPlaced():Boolean { // ... } 具有签名 isPlaced()Z 。 |
这些格式可以包含通配符,以便让单个规则能够涵盖多个方法或类。如需获取在 Android Studio 中使用规则语法编写代码方面的指导帮助,请参阅 Android 基准配置文件插件。
下面显示了一个通配符规则示例:
HSPLandroidx/compose/ui/layout/**->**(**)**
基准配置文件规则支持的类型
基准配置文件规则支持以下类型。如需详细了解这些类型,请参阅 Dalvik 可执行文件 (DEX) 格式。
字符 | 类型 | 说明 |
---|---|---|
B |
byte | 有符号字节 |
C |
char | 采用 UTF-16 编码的 Unicode 字符码位 |
D |
double | 双精度浮点值 |
F |
float | 单精度浮点值 |
I |
int | 整数 |
J |
long | 长整数 |
S |
short | 有符号短数值 |
V |
void | Void |
Z |
boolean | true 或 false |
L (类名称) |
reference | 类名称的实例 |
此外,库还可以定义打包到 AAR 工件中的规则。当您构建 APK 来包含这些工件时,相应规则会合并在一起(类似于清单的合并方式),并编译成 APK 专用的紧凑型二进制 ART 配置文件。
对于搭载 Android 9(API 级别 28)或 Android 7(API 级别 24)并且使用 ProfileInstaller
的设备,当在设备上使用 APK 时,ART 会利用此配置文件在应用安装时对应用的特定子集进行 AOT 编译。
手动衡量应用改进
我们强烈建议您通过基准测试来衡量应用改进。不过,如果您想手动衡量改进,可以先衡量一下未优化的应用启动,以便作为参考。
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 工具构建基准配置文件的紧凑二进制版本。
Profgen-cli 有助于配置文件编译、自省和转译 ART 配置文件,无论目标 SDK 版本如何,都可以在 Android 设备上安装。
Profgen-cli 是一个 CLI,可将基准配置文件的 HRF 编译为其编译格式。该 CLI 还会作为 Android SDK 的一部分提供给 cmdline-tools
库。
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 的发布 build 的路径,以及用于在使用 R8 或 Proguard 时对 APK 进行混淆处理的混淆映射。这样,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
输出文件复制到 APK 的 assets
或 dexopt
文件夹中。
混淆映射
仅当 HRF 使用源符号时,才需要提供混淆映射。如果 HRF 是从已经过混淆处理的发布 build 生成且不需要映射,则可以忽略此选项并将输出复制到 assets
或 dexopt
文件夹。
以传统方式安装基准配置文件
按照历来的做法,基准配置文件会通过两种方式提供给设备。
结合使用 install-multiple
与 DexMetadata
在搭载 API 28 及更高版本的设备上,Play 客户端为要安装的 APK 版本下载 APK 和 DexMetadata (DM) 载荷。DM 包含向设备上的软件包管理器传递的配置文件信息。
该 APK 和 DM 会在单次安装会话期间使用如下方式进行安装:
adb install-multiple base.apk base.dm
Jetpack ProfileInstaller
在搭载 API 级别 29 及更高版本的设备上,Jetpack ProfileInstaller 库提供了一种替代机制,可在 APK 安装到设备上之后安装打包到 assets
或 dexopt
中的配置文件。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>
大多数具有基准配置文件的 APK 中都没有 ProfileInstaller(Play 中约有 45 万个应用,其中 77,000 个应用有 ProfileInstaller),但它实际上存在于每个使用 Compose 的 APK 中。这是因为库可以提供配置文件,而无需声明 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 偏移,因此需要它们来重构类和方法名称。
严格模式默认处于启用状态,此操作会对配置文件与 APK 中的 DEX 文件进行兼容性检查。如果您尝试调试其他工具生成的配置文件,可能会遇到兼容性检查失败问题,导致您无法转储文件以进行调查。如果遇到这种情况,您可以使用 --strict false
停用严格模式。不过,在大多数情况下,您应该启用严格模式。
混淆映射是可选的;它有助于将经过混淆处理的符号重新映射到人类可读的版本,以便于使用。
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 有助提升 SQLite 性能的最佳实践
- 基准配置文件 {:#baseline-profiles}
- 部分唤醒锁定操作卡住