您可以在持续集成 (CI) 环境中运行基准测试来跟踪性能,在应用发布之前就能识别出性能是否有所下降或提升。本页介绍了有关在 CI 环境中进行基准测试的基本信息。
开始在 CI 环境中进行基准测试之前,请考虑捕获和评估结果会在哪些方面不同于常规测试。
结果模糊
虽然基准测试属于插桩测试,但提供的结果不是简单的“通过”或“失败”。基准测试会针对运行基准测试的指定设备提供时间测量结果。通过将一段时间内的结果绘制成图表,使您能够在测量系统中监控变化情况和观察噪声。
使用真实设备
在实体 Android 设备上运行基准测试。虽然基准测试可在模拟器上运行,但强烈建议您不要这样做,因为产生的结果并不代表真实的用户体验,只不过是提供了与主机 OS 和硬件功能相关联的测量值而已。请考虑使用真实设备或者可让您在真实设备上运行测试的服务(例如 Firebase Test Lab)。
运行基准测试
在 CI 流水线中运行基准测试与从 Android Studio 在本地运行基准测试不同。如果在本地运行,您通常需要通过一个 Gradle connectedCheck
任务运行 Android 集成测试。此任务会自动构建和测试 APK,并在已连接到 CI 服务器的设备上运行这些测试。如果是在 CI 环境中运行,此流程通常需要拆分为不同的阶段。
构建
对于 Microbenchmark 库,请运行 Gradle 任务 assemble[VariantName]AndroidTest
,它会创建包含应用代码和经测试代码的测试 APK。
此外,对于 Macrobenchmark 库,您需要分别构建目标 APK 和测试 APK。因此,请运行 :app:assemble[VariantName]
和 :macrobenchmark:assemble[VariantName]
Gradle 任务。
安装和运行
通常,您无需运行 Gradle 任务即可执行这些步骤。请注意,这些步骤可能会被抽象化,具体取决于您是否使用可在真实设备上运行测试的服务。
如需进行安装,请使用 adb install
命令并指定测试 APK 或目标 APK。
运行下列 adb shell am
插桩命令以运行所有基准测试:
adb shell am instrument -w com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
使用 Macrobenchmark 库时,请将常规 androidx.test.runner.AndroidJUnitRunner
用作插桩运行程序。
您可以使用 -e
参数传递与 Gradle 配置中相同的插桩参数。如需了解所有插桩参数选项,请参阅 Microbenchmark 插桩参数或为 Macrobenchmark 添加插桩参数。
例如,您可以设置 dryRunMode
参数以在拉取请求验证流程中运行 Microbenchmark。启用此标志后,Microbenchmark 便只会在单次循环中运行,这样可以验证 Microbenchmark 是否在正常运行,而又不会占用太长的执行时间。
adb shell am instrument -w -e "androidx.benchmark.dryRunMode.enable" "true" com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
如需详细了解如何从命令行运行插桩测试,请参阅使用 adb 运行测试。
锁定时钟
Microbenchmark Gradle 插件提供 ./gradlew lockClocks
命令,用于在已取得 root 权限的设备上锁定 CPU 时钟。如果您有已取得 root 权限的设备(例如“userdebug”build),这对确保稳定性非常有用。您可以使用库的源代码中提供的 lockClocks.sh
Shell 脚本来复制此命令。
您可以直接在 Linux 或 Mac 主机上运行脚本,也可以使用几个 adb 命令将脚本推送给设备:
adb push path/lockClocks.sh /data/local/tmp/lockClocks.sh adb shell /data/local/tmp/lockClocks.sh adb shell rm /data/local/tmp/lockClocks.sh
如果直接在主机上运行 Shell 脚本,它会将这些命令发送给已连接的设备。
如需详细了解为什么锁定 CPU 时钟会有帮助,请参阅如何获得统一的基准测试。
收集结果
每次运行基准测试后,进行基准测试的库都会以 JSON 格式输出测量结果,并将性能分析轨迹输出到 Android 设备上的某个目录中。Macrobenchmark 库会输出多个 perfetto 轨迹文件,每个 MacrobenchmarkRule.measureRepeated
循环的每次测量迭代都有一个。不过,Microbenchmark 只会为每个 BenchmarkRule.measureRepeated
的所有迭代创建一个轨迹文件。性能分析轨迹文件也会输出到同一目录中。
保存和查找文件
如果您使用 Gradle 运行基准测试,这些文件会自动复制到主机的输出目录(位于 build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/
下)。
如果您是使用 adb
命令直接运行,则需要手动拉取这些文件。默认情况下,报告会保存到被测应用在设备上外部存储空间的媒体目录中。为方便起见,该库会将文件路径输出到 Logcat 中。请注意,输出文件夹可能会因运行基准测试的 Android 版本而异。
Benchmark: writing results to /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json
您还可以使用插桩参数 additionalTestOutputDir
配置在设备上保存基准测试报告的位置。您的应用必须能够写入此文件夹。
adb shell am instrument -w -e additionalTestOutputDir /sdcard/Download/ com.example.benchmark/androidx.benchmark.junit4.AndroidBenchmarkRunner
在 Android 10(API 级别 29)及更高版本中,应用的测试默认在存储沙盒中运行,这样可防止您的应用访问应用专属目录之外的文件。为了能够保存到某个全局目录(例如 /sdcard/Download
),请传递以下插桩参数:
-e no-isolated-storage true
您还必须在基准测试的清单中明确允许旧的存储选项:
<application android:requestLegacyExternalStorage="true" ... >
如需了解详情,请参阅暂时停用分区存储。
检索文件
若要从设备中获取生成的文件,请使用 adb pull
命令,将指定的文件拉取到主机的当前目录中:
adb pull /storage/emulated/0/Android/media/com.example.macrobenchmark/com.example.macrobenchmark-benchmarkData.json
如需从指定文件夹中检索所有的 benchmarkData
,请参阅以下代码段:
# The following command pulls all files ending in -benchmarkData.json from the directory
# hierarchy starting at the root /storage/emulated/0/Android.
adb shell find /sdcard/Download -name "*-benchmarkData.json" | tr -d '\r' | xargs -n1 adb pull
轨迹文件(.trace
或 .perfetto-trace
)与 benchmarkData.json
保存在同一文件夹中,因此您可以采用相同的方式收集这些文件。
基准测试数据示例
基准库会生成 JSON 文件,其中包含运行基准测试的设备信息及实际运行的基准测试的信息。以下代码段表示生成的 JSON 文件:
{
"context": {
"build": {
"brand": "google",
"device": "blueline",
"fingerprint": "google/blueline/blueline:12/SP1A.210812.015/7679548:user/release-keys",
"model": "Pixel 3",
"version": {
"sdk": 31
}
},
"cpuCoreCount": 8,
"cpuLocked": false,
"cpuMaxFreqHz": 2803200000,
"memTotalBytes": 3753299968,
"sustainedPerformanceModeEnabled": false
},
"benchmarks": [
{
"name": "startup",
"params": {},
"className": "com.example.macrobenchmark.startup.SampleStartupBenchmark",
"totalRunTimeNs": 4975598256,
"metrics": {
"timeToInitialDisplayMs": {
"minimum": 347.881076,
"maximum": 347.881076,
"median": 347.881076,
"runs": [
347.881076
]
}
},
"sampledMetrics": {},
"warmupIterations": 0,
"repeatIterations": 3,
"thermalThrottleSleepSeconds": 0
}
]
}
其他资源
- 有关如何检测性能下降问题的指导,请参阅在 CI 环境中使用基准测试来解决回归问题。
- 如需了解如何使用 Firebase Test Lab 设置 GitHub Actions,请参阅设置适用于 CI 环境的 Jetpack Macrobenchmark
为您推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 有助提升 SQLite 性能的最佳实践
- 在不使用 Macrobenchmark 的情况下创建和衡量基准配置文件
- 部分唤醒锁定操作卡住