Android Jetpack Benchmark是一个允许Android Studio快速对基于Kotlin或 Java 代码进行基准测试的一个库。该库处理预热,测量代码性能,并将基准测试结果输出到Android Studio控制台。用例包括滚动RecyclerView,膨胀非平凡的View层次结构以及执行数据库查询。
快速接入
- 添加Benchmark测试库
dependencies {
androidTestImplementation "androidx.benchmark:benchmark:1.0.0-alpha03"
}
- 去禁用测试清单文件的 debugging 属性
<!-- Important: disable debuggable for accurate performance results -->
<application
android:debuggable="false"
tools:ignore="HardcodedDebugMode"
tools:replace="android:debuggable"/>
- 添加基准测试,请在androidText目录的测试文件中添加BenchmarkRule实例
@RunWith(AndroidJUnit4::class)
class MyBenchmark {
@get:Rule
val benchmarkRule = BenchmarkRule()
@Test
fun benchmarkSomeWork() = benchmarkRule.measureRepeated {
doSomeWork()
}
}
什么是Benchmark测试
Benchmark测试对于在您的应用中多次运行的CPU工作最有用。 很好的例子是RecyclerView滚动,数据转换/处理以及重复使用的代码片段。
其他类型的代码更难以通过Benchmark测试来衡量。 由于基准测试在循环中运行,因此任何不经常运行或在多次调用时执行不同的代码可能不适合进行基准测试。
- 高速缓存 尽量避免只测量缓存。 例如,自定义视图的布局基准测试可能仅测量布局缓存的性能。 为避免这种情况,您可以在每个循环中传递不同的布局参数。 在其他情况下,例如在测量文件系统性能时,这可能是困难的,因为OS在循环中缓存文件系统。
- 不经常运行的代码 在应用程序启动期间运行一次的代码不太可能通过Android运行时(ART)编译JIT。 因此,在循环中运行时对此代码进行基准测试并不是衡量其性能的现实方法。
对于此类代码,我们建议您在应用中跟踪或分析代码。 请注意,这并不意味着您不能在启动路径中对代码进行基准测试,而是应该选择在循环中运行的代码,并且可能会编译JIT。
完整的项目设置
Jetpack Benchmark库目前处于Alpha状态,需要手动设置Android Studio属性以启用基准模块向导支持。要启用Android Studio模板进行基准测试,请执行以下操作:
- Android Studio 3.5 Beta以上版本
- Android Studio 点击Help -> EditCustom Properties
- 在Android Studio启动文件中添加:
npw.benchmark.template.module=true
- 重启Android Studio
- 创建一个新的module 基准测试模块模板自动配置基准测试的设置。(New -> Module -> Benchmark Module)
写一个基准
基准是标准的仪器测试。 要创建基准,请使用库提供的BenchmarkRule类。 要对活动进行基准测试,请使用ActivityTestRule或ActivityScenarioRule。 要对UI代码进行基准测试,请使用@UiThreadTest。以下代码显示了一个示例基准:
@RunWith(AndroidJUnit4::class)
class ViewBenchmark {
@get:Rule
val benchmarkRule = BenchmarkRule()
@Test
fun simpleViewInflate() {
val context = ApplicationProvider.getApplicationContext()
val inflater = LayoutInflater.from(context)
val root = FrameLayout(context)
benchmarkRule.keepRunning {
inflater.inflate(R.layout.test_simple_view, root, false)
}
}
}
您可以禁用不想测量的代码段的时序,如以下代码示例所示:
@Test
fun bitmapProcessing() = benchmarkRule.measureRepeated {
val input: Bitmap = runWithTimingDisabled { constructTestBitmap() }
processBitmap(input)
}
运行基准(Benchmark)测试
在Android Studio中,基准测试将在您运行应用时运行。 在Android Studio 3.4及更高版本上,您可以看到发送到控制台的输出。
要运行基准测试,请在模块中导航到benchmark / src / androidTest并按Control + Shift + F10(Mac上的Command + Shift + R)。 基准测试结果显示在控制台中
从命令行运行常规的connectedCheck:
./gradlew benchmark:connectedCheck
收集数据
带有其他指标和设备信息的完整基准报告以JSON格式提供。androidx.benchmark Gradle插件默认启用JSON输出。 要在非Gradle构建环境中手动启用JSON输出,请传递一个检测参数androidx.benchmark.output.enable,设置为true。以下是使用adb shell am instrument命令的示例:
adb shell am instrument -w -e "androidx.benchmark.output.enable" "true" com.android.foo/androidx.benchmark.AndroidBenchmarkRunner
JSON报告将写入外部共享下载文件夹中的设备上的磁盘,该文件夹通常位于:
/storage/emulated/0/Download/app_id-benchmarkData.json
当使用Gradle从命令行运行基准测试时,androidx.benchmark Gradle插件会将JSON报告从设备复制到主机。 这些都写在主机上:
project_root/module/build/benchmark_reports/device_id/app_id-benchmarkData.json
时钟稳定性
移动设备上的时钟动态地从高状态(用于性能)变为低状态(以节省功率,或者当设备变热时)。 这些不同的时钟可以使您的基准数量变化很大,因此库提供了解决此问题的方法。
锁定时钟(需要root)
定时钟是获得稳定性能的最佳方式。 它确保时钟永远不会变得足够高以加热设备,或者如果基准测试没有充分利用CPU则会降低。 虽然这是确保稳定性能的最佳方法,但由于需要adb root,因此大多数设备都不支持此功能。
要锁定时钟,请将提供的帮助程序插件添加到主build.gradle文件中的顶级项目的类路径中:
buildscript {
...
dependencies {
...
classpath "androidx.benchmark:benchmark-gradle-plugin:1.0.0-alpha02"
}
}
将插件应用于您正在进行基准测试的模块的build.gradle中:
apply plugin: com.android.app
apply plugin: androidx.benchmark
...
这会将基准Gradle任务添加到您的项目中,包括./gradlew lockClocks和./gradlew unlockClocks。 使用这些任务可以使用adb锁定和解锁设备的CPU。
如果adb可以看到多个设备,请使用环境变量ANDROID_SERIAL指定Gradle任务应对哪个设备进行操作:
ANDROID_SERIAL=device-id-from-adb-devices ./gradlew lockClocks
持续的表现模式
Window.setSustainedPerformanceMode()是某些设备支持的功能,使应用程序可以选择较低的最大CPU频率。 在支持的设备上运行时,Benchmark库使用此API的组合并启动其自身的活动,以防止热量限制和稳定结果。
在使用基准模块模板创建的模块中已启用此功能。 要在其他模块中启用此功能,请将库提供的检测运行器添加到基准模块的build.gradle文件中: project_root/benchmark/build.gradle
android {
defaultConfig {
testInstrumentationRunner "androidx.benchmark.AndroidBenchmarkRunner"
}
}
跑步者启动不透明的全屏活动,以确保基准测试在前台运行,而无需任何其他应用程序绘图。
自动执行暂停
如果既不使用时钟锁定也不使用持续性能,则库会执行自动热量调节检测。 启用后,内部基准测试会定期运行,以确定设备温度何时达到足以降低CPU性能的程度。 当检测到降低的CPU性能时,磁带库暂停执行以使设备冷却,并重试当前的基准测试。
警告
该库检测到以下条件,以确保您的项目和环境设置为发布准确性能:
Debuggable设置为false。 正在使用物理设备,而不是仿真器。 如果设备已植根,时钟将被锁定。 设备上的电池电量充足。 如果上述任何检查失败,则在通过预先添加“DEBUGGABLE_”报告结果时,故意破坏测试名称。 这样做是为了阻止使用不准确的测量。
测试demo
以下项目中提供了示例基准代码:
- https://github.com/googlesamples/android-performance
- https://github.com/googlesamples/android-architecture-components
示例项目包括:
- BenchmarkSample 这是一个独立的示例,展示了如何使用基准模块来测量代码和UI。
- PagingWithNetworkSample
Android Architecture Components示例,展示了如何对RecyclerView性能进行基准测试。 - WorkManagerSample
Android Architecture Components示例,演示如何对WorkManager工作程序进行基准测试。