Macrobenchmark 库适用于测试应用的较大用例,包括应用启动和复杂的界面操作,例如滚动 RecyclerView
或运行动画。如果您希望测试较小的代码区域,请参阅 Microbenchmark 库。
该库会将基准化分析结果的更多详细信息输出到 Android Studio 控制台和 JSON 文件。此外,它还提供跟踪文件,您可以在 Android Studio 中加载和分析这些文件。
您还可以在持续集成 (CI) 环境中使用 Macrobenchmark 库,如在持续集成环境中运行基准所述。
项目设置
我们建议您将 Macrobenchmark 与最新版本的 Android Studio(Bumblebee 2021.1.1 或更高版本)搭配使用,因为该版本的 Android Studio 中提供了可与 Macrobenchmark 集成的新功能。
设置 Macrobenchmark 模块
宏基准需要一个独立于应用代码的 com.android.test
模块来负责运行衡量应用的测试。
Bumblebee(或更高版本)
在 Android Studio Bumblebee 2021.1.1 中,我们提供了一个模板来简化 Macrobenchmark 模块设置。基准化分析模块模板会自动在项目中创建一个模块(包含一个示例启动基准),用于衡量通过应用模块构建的应用。
如需使用模块模板创建新模块,请执行以下操作:
在 Android Studio 的 Project 面板中右键点击您的项目或模块,然后依次点击 New > Module。
从 Templates 窗格中选择 Benchmark。
您可以自定义目标应用(要进行基准测试的应用),以及新的 Macrobenchmark 模块的软件包和模块名称。
点击 Finish。
Arctic Fox
在 Arctic Fox 中,您要创建一个库模块,然后将其转换为测试模块。
- 在 Android Studio 的 Project 面板中右键点击您的项目或模块,然后依次点击 New > Module。
- 在 Templates 窗格中选择 Android Library。
- 输入
macrobenchmark
作为模块名称。 - 将 Minimum SDK 设置为 API 23: Android M
- 点击 Finish。
修改 Gradle 文件
按如下所示自定义 Macrobenchmark 模块的 build.gradle
:
- 将插件从
com.android.library
更改为com.android.test
。apply plugin 'com.android.test'
- 在
android {}
代码块中添加其他所需的测试模块属性:Groovy
android { // ... // Note that your module name may have different name targetProjectPath = ":app" // Enable the benchmark to run separately from the app process experimentalProperties["android.experimental.self-instrumenting"] = true buildTypes { // declare a build type to match the target app's build type benchmark { debuggable = true signingConfig = debug.signingConfig } } }
Kotlin
android { // ... // Note that your module name may have different name targetProjectPath = ":app" // Enable the benchmark to run separately from the app process experimentalProperties["android.experimental.self-instrumenting"] = true buildTypes { // declare a build type to match the target app's build type create("benchmark") { isDebuggable = true signingConfig = signingConfigs.getByName("debug") } } }
- 将所有名为
testImplementation
或androidTestImplementation
的依赖项更改为implementation
。 - 添加 Macrobenchmark 库的依赖项:
implementation 'androidx.benchmark:benchmark-macro-junit4:1.1.0-beta03'
- 仅允许此模块使用
benchmark
buildType。在android{}
代码块之后、dependencies{}
代码块之前,添加以下代码:Groovy
androidComponents { beforeVariants(selector().all()) { // enable only the benchmark buildType, since we only want to measure close to release performance enabled = buildType == 'benchmark' } }
Kotlin
androidComponents { beforeVariants { // enable only the benchmark buildType, since we only want to measure close to release performance it.enable = it.buildType == "benchmark" } }
- 简化目录结构。
在
com.android.test
模块中,对于所有测试,只有一个源目录。删除包括src/test
和src/androidTest
在内的其他源目录,因为系统不会使用这些目录。
设置应用
若要对应用(称为该宏基准的目标)进行基准测试,该应用必须 profileable
,这样系统才能读取详细的跟踪信息。在应用的 AndroidManifest.xml
的 <application>
标记中启用此状态:
<!-- enable profiling by macrobenchmark -->
<profileable
android:shell="true"
tools:targetApi="q" />
尽可能将进行基准测试的应用配置为接近发布版本(或正式版)。将其设置为不可调试,最好开启“缩减大小”功能,以提高性能。通常,您可以通过创建发布变体的副本来实现此目的,该副本会执行同样的操作,但使用调试密钥在本地签名。或者,您也可以使用 initWith
指示 Gradle 为您执行此操作:
Groovy
buildTypes { release { minifyEnabled true shrinkResources true proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' } benchmark { initWith buildTypes.release signingConfig signingConfigs.debug
Kotlin
buildTypes { getByName("release") { isMinifyEnabled = true isShrinkResources = true proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt")) } create("benchmark") { initWith(getByName("release")) signingConfig = signingConfigs.getByName("debug") } }
执行 Gradle 同步,打开左侧的 Build Variants 面板,然后选择应用和 Macrobenchmark 模块的要进行基准测试的变体。这可确保运行基准的操作将会构建并测试应用的正确变体:
设置多模块应用
如果您的应用有多个 Gradle 模块,您需要确保构建脚本知道要编译哪个 build 变体。如果缺少这项设置,新添加的 benchmark
buildType 会导致构建失败,并提供以下错误消息:
> Could not resolve project :shared.
Required by:
project :app
> No matching variant of project :shared was found.
您可以通过将 matchingFallbacks
属性添加到 :macrobenchmark
和 :app
模块的 benchmark
buildType 中来解决此问题。其余 Gradle 模块可以具有与之前相同的配置。
Groovy
benchmark { initWith buildTypes.release signingConfig signingConfigs.debug matchingFallbacks = ['release'] }
Kotlin
create("benchmark") { initWith(getByName("release")) signingConfig = signingConfigs.getByName("debug") matchingFallbacks += listOf('release') }
在项目中选择 build 变体时,请为 :app
和 :macrobenchmark
模块选择 benchmark
,为应用中的任何其他模块选择 release
,如下图所示:
如需了解详情,请查看变体感知型依赖项管理。
创建微基准类
基准测试通过 Macrobenchmark 库中的 MacrobenchmarkRule
JUnit4 规则 API 提供。它包含 measureRepeated
方法,您可以通过该方法指定有关应如何运行目标应用并对其进行基准测试的各种条件。
您至少需要指定目标应用的 packageName
、您要衡量的 metrics
以及基准应该运行的 iterations
次数。
Kotlin
@LargeTest @RunWith(AndroidJUnit4::class) class SampleStartupBenchmark { @get:Rule val benchmarkRule = MacrobenchmarkRule() @Test fun startup() = benchmarkRule.measureRepeated( packageName = TARGET_PACKAGE, metrics = listOf(StartupTimingMetric()), iterations = 5, setupBlock = { // Press home button before each run to ensure the starting activity isn't visible. pressHome() } ) { // starts default launch activity startActivityAndWait() } }
Java
@LargeTest @RunWith(AndroidJUnit4.class) public class SampleStartupBenchmark { @Rule public MacrobenchmarkRule benchmarkRule = new MacrobenchmarkRule(); @Test public void startup() { benchmarkRule.measureRepeated( /* packageName */ TARGET_PACKAGE, /* metrics */ Arrays.asList(new StartupTimingMetric()), /* iterations */ 5, /* measureBlock */ scope -> { // starts default launch activity scope.startActivityAndWait(); return Unit.INSTANCE; } ); } }
如需有关如何自定义基准的所有选项,请参阅自定义基准部分。
运行基准
在 Android Studio 中运行测试,以衡量应用在设备上的性能。您可以像使用测试类或方法旁边的边线操作运行任何其他 @Test
一样运行基准,如下图所示。
您也可以执行 connectedCheck 命令,从命令行运行 Gradle 模块中的所有基准:
./gradlew :macrobenchmark:connectedCheck
或者,运行单个测试:
./gradlew :macrobenchmark:connectedCheck -P android.testInstrumentationRunnerArguments.class=com.example.macrobenchmark.startup.SampleStartupBenchmark#startup
如需了解如何在持续集成环境中运行和监控基准,请参阅在持续集成环境中运行基准部分。
基准结果
基准运行成功后,指标会直接显示在 Android Studio 中,还会以 JSON 文件形式输出以供集成环境使用。每次衡量的迭代过程均会捕获单独的系统跟踪文件。点击 Test Results 窗格中的其中一个链接,可以打开这些结果跟踪文件,如下图所示。
跟踪文件加载完成后,Android Studio 会提示您选择要分析的进程。系统会预先填充目标应用进程:
跟踪文件加载完成后,Studio 将在 CPU 性能剖析器工具中显示结果:
手动访问跟踪文件
如果您使用的是旧版 Android Studio(Arctic Fox 2020.3.1 之前的版本),或者要使用 Perfetto 工具分析跟踪文件,还需要执行几个额外的步骤。您可以使用 Perfetto 检查跟踪期间整个设备上发生的所有进程,而 Android Studio 的 CPU 性能分析器只能检查单个进程。
如果您从 Android Studio 或使用 Gradle 命令行调用测试,系统会自动将跟踪文件从设备复制到主机。这些报告将写入主机上的以下位置:
project_root/module/build/outputs/connected_android_test_additional_output/debugAndroidTest/connected/device_id/TrivialStartupBenchmark_startup[mode=COLD]_iter002.perfetto-trace
将跟踪文件复制到主机系统后,您可以在 Android Studio 中通过依次点击 File > Open 菜单打开此跟踪文件。此时系统会显示上一部分中显示的性能分析器工具视图。
配置错误
如果应用配置有误(可调试或不可分析),微基准就会返回错误,而不会报告不正确或不完整的衡量结果。您可以使用 androidx.benchmark.suppressErrors
参数抑制这些错误。
如果尝试衡量模拟器,或在电量不足的设备上进行衡量,系统也会抛出错误,因为这些情况可能会影响核心可用性和时钟速度。
自定义基准
measureRepeated
函数接受各种参数,这些参数会影响库收集的指标、应用的启动和编译方式或基准将运行的迭代次数。
捕获指标
指标是从基准中提取的主要信息类型。可用选项包括 StartupTimingMetric
、FrameTimingMetric
和 TraceSectionMetric
。如需详细了解这些选项,请参阅捕获指标页面。
利用自定义事件改进跟踪数据
利用自定义跟踪事件进行应用插桩非常有用,这些事件会与跟踪报告的其余部分一起显示,有助于找出应用特有的问题。如需详细了解如何创建自定义跟踪事件,请参阅定义自定义事件指南。
CompilationMode
宏基准可以指定 CompilationMode,用于定义应该将应用的多大部分从 DEX 字节码(APK 中的字节码格式)预编译为机器代码(类似于预编译的 C++)。
默认情况下,系统会使用 CompilationMode.DEFAULT
运行宏基准,这会在 Android 7(API 级别 24)及更高版本上安装基准配置文件(如果有)。如果您使用的是 Android 6(API 级别 23)或更低版本,编译模式会将 APK 完全编译为默认系统行为。
如果目标应用同时包含基准配置文件和 ProfileInstaller
库,您可以安装基准配置文件。
在 Android 7 及更高版本中,您可以自定义 CompilationMode
以影响设备上的预编译量,从而模拟不同级别的预先 (AOT) 编译或 JIT 缓存。请参阅 CompilationMode.Full
、CompilationMode.Partial
和 CompilationMode.None
。
此功能基于 ART 编译命令构建而成。每次基准测试都会在开始之前清除分析数据,确保基准测试之间互不干扰。
StartupMode
如需执行 activity 启动,您可以传递一种预定义的启动模式(COLD
、WARM
或 HOT
中的一种)。此参数会更改 activity 的启动方式,以及测试开始时的进程状态。
如需详细了解启动类型,请参阅 Android Vitals 启动文档。
示例
GitHub 上提供了一个示例项目,该项目位于 android/performance-samples 代码库中。
提供反馈
如需针对 Jetpack Macrobenchmark 报告问题或提交功能请求,请参阅公开问题跟踪器。