Android NDK开发详解之调试和性能分析的手动创建和衡量基准配置文件

我们强烈建议利用 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]

有关详细说明,请参阅下表:
在这里插入图片描述

这些格式可以包含通配符,以便让单个规则能够涵盖多个方法或类。如需获取在 Android Studio 中使用规则语法编写代码方面的指导帮助,请参阅 Android 基准配置文件插件。

下面显示了一个通配符规则示例:


HSPLandroidx/compose/ui/layout/**->**(**)**

基准配置文件规则支持的类型

基准配置文件规则支持以下类型。如需详细了解这些类型,请参阅 Dalvik 可执行文件 (DEX) 格式。

在这里插入图片描述

此外,库还可以定义打包到 AAR 工件中的规则。当您构建 APK 来包含这些工件时,相应规则会合并在一起(类似于清单的合并方式),并编译成 APK 专用的紧凑型二进制 ART 配置文件。

对于搭载 Android 9(API 级别 28)或 Android 7(API 级别 24)并且使用 ProfileInstaller 的设备,当在设备上使用 APK 时,ART 会利用此配置文件在应用安装时对应用的特定子集进行 AOT 编译。

手动衡量应用改进

注意:为了提高稳定性和准确性,我们建议使用 Macrobenchmark 来衡量性能影响,因为 Macrobenchmark 可以在一个循环中反复进行衡量、捕获性能调试轨迹,并提高可靠性(例如通过清除操作系统的磁盘缓存)。
我们强烈建议您通过基准测试来衡量应用改进。不过,如果您想手动衡量改进,可以先衡量一下未优化的应用启动,以便作为参考。

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"

接下来,旁加载基准配置文件。

注意:此工作流仅适用于 Android 9 (API 28) 到 Android 11 (API 30)。如需了解详情,请参阅各种 Android 版本的编译行为。


# 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"

注意:为了提高稳定性和准确性,建议使用 Macrobenchmark 来衡量性能影响,因为 Macrobenchmark 可以在一个循环中反复进行衡量、捕获性能调试的轨迹,并提高可靠性(例如,通过清除操作系统的磁盘缓存)。

基准配置文件和 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 配置文件格式转码为另一种格式。

配置文件格式和平台版本

注意:将配置文件捆绑到 assets 文件夹中时,应始终采用 v0_1_0_p 格式。
选择配置文件格式时,会出现以下选项:

在这里插入图片描述

将 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

注意:正确的配置文件 DM 载荷会根据发出 APK 下载请求的设备 SDK 版本来提供。Play 会将封装为 v0_1_0_p 的配置文件转码成用于提供正确版本的每个已知配置文件版本,从而生成一个元组。

Jetpack ProfileInstaller

在搭载 API 级别 29 及更高版本的设备上,Jetpack ProfileInstaller 库提供了一种替代机制,可在 APK 安装到设备上之后安装打包到 assets 或 dexopt 中的配置文件。ProfileInstaller 由 ProfileInstallReceiver 或应用直接调用。

ProfileInstaller 库会根据目标设备 SDK 版本对配置文件进行转码,并将配置文件复制到设备上的 cur 目录(设备上的 ART 配置文件的软件包专用暂存目录)中。

设备处于空闲状态后,设备上名为 bg-dexopt 的进程就会对配置文件进行编译。

注意:即使只有 Android P 设备及更高版本支持 Play 使用 install-multiple 分发基准配置文件,ProfileInstaller 也可以将 ART 配置文件向后移植到 Android N。因此,在使用基准配置文件时,请务必声明对 ProfileInstaller 库的依赖项。

旁加载基准配置文件

本部分介绍了如何在具有 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 停用严格模式。不过,在大多数情况下,您应该启用严格模式。

混淆映射是可选的;它有助于将经过混淆处理的符号重新映射到人类可读的版本,以便于使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

五一编程

程序之路有我与你同行

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值