Las métricas son el tipo principal de información que se extrae de tus comparativas. Se pasan a la función measureRepeated como un List, que te permite especificar varias métricas medidas a la vez. Se requiere al menos un tipo de métrica para que se ejecute la comparativa.
En el siguiente fragmento de código, se capturan las latencias de fotogramas y las métricas personalizadas de la sección de registro para una interfaz de diseño diferido de 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)
}
}
}
En el siguiente ejemplo, EntryRowCustomTrace representa una sección de registro personalizada definida dentro de las capas de elementos componibles con el wrapper de bloque trace(sectionName) { ... } estándar de Kotlin. Para proporcionar datos para TraceSectionMetric, debes encapsular los componentes de la IU de destino dentro del wrapper de bloque trace estándar del tiempo de ejecución de Jetpack en la base de código de producción de tu aplicación:
@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)
)
}
}
}
Los resultados de comparativas se muestran directamente en la pestaña de terminal Benchmark dentro de Android Studio, como se muestra en la figura 1. Si se definen varias métricas, todos sus datos calculados se combinan en la ventana de resumen.

TraceSectionMetric y FrameTimingMetric para un diseño moderno de Compose.StartupTimingMetric, FrameTimingMetric, TraceSectionMetric y PowerMetric se explican en detalle a continuación. Para obtener una lista completa de las métricas de comparativas disponibles, consulta las subclases de Metric en la referencia de la API.
StartupTimingMetric
StartupTimingMetric captura las métricas de tiempo de inicio de la app con los siguientes valores:
timeToInitialDisplayMs: Es la cantidad de tiempo que transcurre desde que el sistema recibe un intent de inicio hasta que renderiza el primer fotograma de la pantalla de destino.timeToFullDisplayMs: Es la cantidad de tiempo que transcurre desde que el sistema recibe un intent de inicio hasta que la app informa que se visualiza por completo a través de los mecanismos internos de generación de informes de la plataforma. La medición se detiene cuando se completa la renderización del primer fotograma después de la señal de dibujo completo (o que lo contiene).
StartupTimingMetric genera los valores mínimos, medios y máximos de las iteraciones de inicio. Para evaluar la mejora del inicio, enfócate siempre en los valores medios, ya que proporcionan la mejor estimación de los tiempos de inicio típicos de los usuarios.
En una arquitectura que prioriza Compose, no intentes invocar activity.reportFullyDrawn de forma manual. En su lugar, usa las utilidades asíncronas seguras para Compose ReportDrawn, ReportDrawnWhen o ReportDrawnAfter dentro de tus elementos componibles de pantalla para indicarle automáticamente a Macrobenchmark cuándo terminaron de renderizarse tus datos de red asíncronos o los estados complejos de la IU.
Para obtener más información sobre el análisis y la optimización del rendimiento de la inicialización, consulta Tiempo de inicio de la app.
FrameTimingMetric
FrameTimingMetric captura información de latencia precisa de los fotogramas que produce un recorrido de comparativa, como el desplazamiento por una lista o una animación de diseño de IU compleja, y genera los siguientes valores de diagnóstico:
frameOverrunMs: Es la cantidad de tiempo por el que un fotograma determinado no pudo cumplir su plazo. Los números positivos indican un fotograma descartado acompañado de un bloqueo o salto visible. Los números negativos indican cuánto más rápido se completó un fotograma en relación con el plazo de hardware del subsistema. Nota: Esta métrica solo está disponible en Android 12 (nivel de API 31) y versiones posteriores.frameDurationCpuMs: Es la cantidad de tiempo que el fotograma pasó produciéndose activamente en la CPU, tanto en el subproceso de IU de la aplicación principal como en elRenderThreadde Compose.
Estas mediciones se recopilan en una distribución de percentiles 50, 90, 95 y 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
Cuando optimices las jerarquías de diseño de Jetpack Compose, observa los fotogramas con el peor rendimiento (los límites de P95 y P99). Si frameOverrunMs aumenta repentinamente a números enteros positivos en los percentiles altos, indica que las recomposiciones están deteniendo el subproceso principal durante las animaciones de desplazamiento intensas.
Para obtener estadísticas más detalladas sobre cómo identificar y resolver los fotogramas lentos, consulta Rendimiento de Jetpack Compose.
TraceSectionMetric
TraceSectionMetric captura la cantidad de veces que se produce una sección de registro específica y la cantidad absoluta de tiempo que tarda en ejecutarse. Para el seguimiento del tiempo, muestra el tiempo mínimo, el máximo y la mediana en milisegundos. La sección de registro de destino se define con la llamada a función trace(sectionName) o los límites de bloque de nivel inferior entre Trace.beginSection(sectionName) y Trace.endSection(), o bien sus variantes asíncronas.
EntryRowCustomTraceCount min 20.0, median 28.0, max 50.0
EntryRowCustomTraceSumMs min 34.9, median 44.4, max 66.6
De forma predeterminada, la métrica solo genera secciones de registro compiladas directamente desde los archivos binarios del paquete de tu propia aplicación. Para incluir procesos que se originan fuera del límite del paquete de tu app, establece la propiedad targetPackageOnly = false.
Cuando trabajas en el registro del tiempo de ejecución de Jetpack Compose, puedes mostrar funciones de componibilidad individuales en los gráficos de registro del sistema sin escribir wrappers de registro manuales habilitando el registro de composición.
Si bien agregar la dependencia de androidx.compose.runtime:runtime-tracing a tu aplicación de destino es suficiente para los registros manuales del generador de perfiles, capturar estos registros de forma programática dentro de una ejecución de Macrobenchmark requiere configuración adicional dentro de tu módulo de benchmark.
Para obtener instrucciones completas sobre la configuración, consulta Cómo capturar un registro con Jetpack Macrobenchmark.
PowerMetric
PowerMetric captura el cambio en la alimentación o la energía durante la ejecución de Macrobenchmark. Cada categoría seleccionada se divide en sus componentes de hardware medibles, mientras que las categorías sin seleccionar se agrupan en un bucket "sin seleccionar".
Requisito de hardware: Estas métricas miden el consumo en todo el sistema, en lugar de los cálculos por app. Por lo tanto, la recopilación de datos se limita a los dispositivos físicos Google Pixel 6, Pixel 6 Pro y dispositivos físicos más recientes.
La métrica genera dos mediciones por categoría:
power<category>Uw: La cantidad de energía consumida durante la prueba en esta categoría (medida en microvatios).energy<category>Uws: Es la cantidad total de energía transferida por unidad de tiempo durante la prueba en esta categoría (medida en microvatios-segundos).
Entre las categorías, se incluyen las siguientes:
CPUDISPLAYGPUGPSMEMORYMACHINE_LEARNINGNETWORKUNCATEGORIZED
Con algunas categorías, como CPU, puede ser difícil separar el trabajo que realizan otros procesos del que realiza tu propia app. Para minimizar la interferencia, quita o restringe apps y cuentas innecesarias.
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
Cómo analizar los subsistemas principales
PowerMetric captura el cambio en la alimentación o la energía durante la prueba para las categorías de energía proporcionadas. Cada categoría que seleccionas se divide en sus subcomponentes medibles, y las categorías sin seleccionar se agregan a la métrica "sin seleccionar".
Los resultados de la terminal se corresponden con la configuración que solicitaste:
powerCategoryCpuUw: La cantidad de energía que consumió la CPU durante la prueba.powerCategoryGpuUw: Es la cantidad de energía que consumió la GPU durante la prueba.powerUnselectedUw: Es la potencia agregada que consumen todas las categorías de hardware disponibles que no se solicitaron de forma explícita en tu mapa de inicialización.
Para evitar picos erráticos de datos en los rieles de hardware durante una ejecución, fija el brillo de la pantalla de bloqueo en un valor fijo, mantén una temperatura estable del dispositivo y cierra los procesos en segundo plano que compiten antes de iniciar el bucle de Macrobenchmark.
Recursos adicionales
Mira contenido
Recomendaciones para ti
- Nota: El texto del vínculo se muestra cuando JavaScript está desactivado
- Cómo crear perfiles de Baseline {:#creating-profile-rules}
- Cómo escribir una macrocomparativa
- Optimización y análisis de inicio de la app {:#app-startup-analysis-optimization}