指标是指从基准测试中提取的主要信息类型。这些指标会以 List 的形式传递给 measureRepeated 函数;也就是说,您可以一次性指定多个测量指标。基准测试必须至少包含一种指标类型才能运行。
以下代码段会捕获 Jetpack Compose 延迟布局界面的帧时间和自定义的轨迹部分指标:
@OptIn(ExperimentalMetricApi::class)
@Test
fun scrollComposeList() {
benchmarkRule.measureRepeated(
// [START_EXCLUDE]
packageName = TARGET_PACKAGE,
metrics = listOf(
FrameTimingMetric(),
// Measure power usage. This is supported on Pixel 6 and later.
PowerMetric(PowerMetric.Type.Power(
mapOf(
PowerCategory.CPU to PowerCategoryDisplayLevel.TOTAL,
PowerCategory.DISPLAY to PowerCategoryDisplayLevel.TOTAL,
PowerCategory.GPU to PowerCategoryDisplayLevel.TOTAL,
PowerCategory.NETWORK to PowerCategoryDisplayLevel.TOTAL,
)
)),
// Measure custom trace sections by name EntryRow (which is added to the EntryRow composable).
// Mode.Sum measures combined duration and also how many times it occurred in the trace.
// This way, you can estimate whether a composable recomposes more than it should.
TraceSectionMetric("EntryRowCustomTrace", TraceSectionMetric.Mode.Sum),
// This trace section takes into account the SQL wildcard character %,
// which can find trace sections without the full name.
// This way, you can measure composables produced by the composition tracing
// and measure how long they took and how many times they recomposed.
// WARNING: This metric only shows results when running with composition tracing, otherwise it won't be visible in the outputs.
TraceSectionMetric("%EntryRow%", TraceSectionMetric.Mode.Sum),
),
// Try switching to different compilation modes to see the effect
// it has on frame timing metrics.
compilationMode = CompilationMode.None(),
startupMode = StartupMode.WARM, // restarts activity each iteration
iterations = DEFAULT_ITERATIONS,
// [END_EXCLUDE]
setupBlock = {
uiAutomator {
// Before starting to measure, navigate to the UI to be measured.
startIntent(Intent("$packageName.COMPOSE_ACTIVITY"))
}
}
) {
uiAutomator {
onElement { isScrollable }.fling(Direction.DOWN)
}
}
}
在以下示例中,EntryRowCustomTrace 表示使用标准 Kotlin trace(sectionName) { ... } 块封装容器在可组合项层内定义的自定义轨迹部分。如需为
TraceSectionMetric 提供数据,您必须使用标准 Jetpack 运行时 trace 块封装容器将目标界面组件封装在应用的生产代码库中:
@Composable
private fun EntryRow(entry: Entry, modifier: Modifier = Modifier) = trace("EntryRowCustomTrace") {
Card(modifier = modifier) {
Row(verticalAlignment = Alignment.CenterVertically) {
Text(
text = entry.contents,
modifier = Modifier
.padding(16.dp)
.wrapContentSize()
)
Spacer(modifier = Modifier.weight(1f))
Checkbox(
checked = false,
onCheckedChange = {},
modifier = Modifier.padding(16.dp)
)
}
}
}
基准测试结果会直接输出到 Android Studio 内的 Benchmark 终端标签页,如图 1 所示。如果定义了多个指标,则所有这些指标的计算数据点都会在摘要窗口中合并到一处。
TraceSectionMetric 和 FrameTimingMetric 的合并控制台结果。下文将详细介绍 StartupTimingMetric、FrameTimingMetric、TraceSectionMetric 和
PowerMetric。如需查看可用
基准测试指标的完整列表,请参阅 API
参考中的 Metric 的子类。
StartupTimingMetric
StartupTimingMetric 可捕获提供以下值的应用启动时间指标:
timeToInitialDisplayMs:从系统收到启动 intent 到渲染目标屏幕的第一帧所用的时间。timeToFullDisplayMs:从系统收到启动 intent 到应用使用内部平台报告机制报告已完全绘制所用的时间。当跟随在完全绘制信号之后或包含该信号的第一帧完成渲染时,测量即会停止。
StartupTimingMetric 会输出启动迭代的最小值、中位数值和最大值。如需评估启动方面的改进,请始终重点关注中位数值,因为它们能够最准确地估算典型用户启动时间。
在以 Compose 为先的架构中,请勿尝试手动调用 activity.reportFullyDrawn。相反,请在屏幕可组合项中使用 Compose 安全的异步
实用程序 ReportDrawn、ReportDrawnWhen 或 ReportDrawnAfter
,以便在异步网络数据或复杂界面状态完成渲染时自动向 Macrobenchmark 发出信号。
如需详细了解如何分析和优化初始化性能, 请参阅 应用启动时间。
FrameTimingMetric
FrameTimingMetric 会捕获基准测试历程(例如滚动列表或复杂的界面布局动画)所生成帧的精确时间信息,并输出以下诊断值:
frameOverrunMs:给定帧完全呈现用时与其呈现时限相差的时长。 正数表示出现了丢帧和可见的卡顿。负数表示帧完全呈现用时比子系统硬件呈现时限少多少时间。注意:此指标仅适用于 Android 12(API 级别 31)及更高版本。frameDurationCpuMs:帧在主应用界面线程和 ComposeRenderThread中积极生成所用的时间。
系统会收集分布在第 50 个、第 90 个、第 95 个和第 99 个百分位的以上测量值:
frameDurationCpuMs P50 3.5, P90 6.0, P95 6.4, P99 11.0
frameOverrunMs P50 -11.6, P90 -7.2, P95 -7.1, P99 -1.2
优化 Jetpack Compose 布局层次结构时,请查看性能最差的帧(第 95 个和第 99 个百分位边界)。如果
frameOverrunMs 在高百分位时飙升为正整数,则表示在大量滚动动画期间,重组会使主线程停滞。
如需深入了解如何识别和解决帧缓慢问题,请参阅 Jetpack Compose 性能。
TraceSectionMetric
TraceSectionMetric 会捕获特定轨迹部分发生的次数以及执行该轨迹部分所用的绝对时间。对于时间跟踪,它会输出该时间的最小值、中位数和最大值(以毫秒为单位)。目标
轨迹部分是通过函数调用trace(sectionName)
或者
Trace.beginSection(sectionName)和Trace.endSection()之间的较低级别块边界(或其
异步变体)来定义。
EntryRowCustomTraceCount min 20.0, median 28.0, max 50.0
EntryRowCustomTraceSumMs min 34.9, median 44.4, max 66.6
默认情况下,该指标仅输出直接从您自己的应用软件包二进制文件编译的轨迹部分。如需加入源自应用软件包边界之外的进程,请设置属性
targetPackageOnly = false。
使用 Jetpack Compose 运行时跟踪时,您可以通过启用 组合跟踪在系统跟踪图表中显示各个 可组合函数,而无需编写手动跟踪 封装容器。
虽然将 androidx.compose.runtime:runtime-tracing 依赖项添加到目标应用足以进行手动分析器跟踪,但在
Macrobenchmark 运行中以编程方式捕获这些跟踪记录需要在基准测试模块内进行其他配置。
如需查看完整的设置说明,请参阅使用 Jetpack Macrobenchmark捕获跟踪记录。
PowerMetric
PowerMetric 会捕获 Macrobenchmark 运行期间的耗电量或能量变化。每个选定类别可拆分为多个可衡量的硬件组件,而未选择的类别则分组到“未选择”存储分区中。
硬件要求:这些指标测量的是系统级消耗量,而不是 每个应用的计算量。因此,数据收集仅限于实体 Google Pixel 6、Pixel 6 Pro 和更新的实体设备。
该指标会针对每个类别输出两个测量值:
power<category>Uw:此类别在您的 测试期间的耗电量(以微瓦为单位)。energy<category>Uws:此类别在测试期间每单位时间传输的总能量(以微瓦秒为单位)。
类别包括以下各项:
CPUDISPLAYGPUGPSMEMORYMACHINE_LEARNINGNETWORKUNCATEGORIZED
对于某些类别(如 CPU),可能很难将其他进程执行的工作与您自己的应用执行的工作区分开来。请移除或限制不必要的应用和账号,最大限度地减少干扰。
powerCategoryCpuUw min 300.2, median 346.1, max 519.6
powerCategoryDisplayUw min 319.8, median 325.8, max 329.7
powerCategoryGpuUw min 18.8, median 23.3, max 36.9
powerCategoryNetworkUw min 97.3, median 123.3, max 681.3
powerTotalUw min 1234.8, median 1316.6, max 2112.4
powerUnselectedUw min 483.3, median 512.6, max 561.7
分析核心子系统
PowerMetric 会捕获所提供的电源类别在测试期间的耗电量或能量变化。每个选定类别可拆分为多个可衡量的子组件,而未选择的类别则添加到“未选择”指标中。
终端输出映射到您请求的配置:
powerCategoryCpuUw:CPU 在测试期间的耗电量。powerCategoryGpuUw:GPU 在测试期间的耗电量。powerUnselectedUw:在初始化映射中未 明确请求的所有可用硬件类别的总耗电量。
为防止运行期间硬件轨道上出现不稳定的数据峰值,请将屏幕亮度锁定为固定值,保持设备温度稳定,并在启动 Macrobenchmark 循环之前关闭竞争性后台进程。
其他资源
查看内容
为你推荐
- 注意:当 JavaScript 处于关闭状态时,系统会显示链接文字
- 创建基准配置文件 {:#creating-profile-rules}
- 编写 Macrobenchmark
- 应用启动分析和优化 {:#app-startup-analysis-optimization}