Benchmark your app

Benchmarking is a way to test the performance of your application. You can regularly run benchmarks to help analyze and debug performance problems and to ensure that there are not any regressions introduced in recent changes.

There are two benchmarking libraries and approaches that Android offers, which are useful for analyzing and testing different kinds of situations in your application: Benchmark and Macrobenchmark.

Benchmark versus Macrobenchmark

The Jetpack Benchmark library allows you to benchmark app code directly in a loop. It is designed for measuring CPU work that will assess best-case performance (warmed up JIT, disk accesses cached), like you might see with an inner loop or a specific hot function.

Benchmarks are written to directly call the code being benchmarked, like this:

@get:Rule
val benchmarkRule = BenchmarkRule()

@Test
fun myBenchmarkTest() {
    benchmarkRule.measureRepeated {
        // code or function call that you want to benchmark
    }
}

The benchmark library reports information about only your application, not about the system overall. Because of this, it is best used for analyzing performance of situations specific to the app, not ones that might relate to overall system issues. For example, application startup involves operations happening both outside the app and before app code is executed, so it is useful to see that information when researching startup performance problems. Microbenchmark tests are not useful for trying to fix this use case.

Macrobenchmark measures larger end-user interactions, such as startup, scrolling, and animations. Unlike the benchmark library, Macrobenchmark injects events and monitors results externally, from a test application that you provide.

Macrobenchmark provides direct control over the performance environment being tested. For example, you can specify cold, first-time install startup performance, in addition to "warm" and "hot" startup options, as show in this example adapted from the Macrobenchmark sample:

@Test
fun startup() = benchmarkRule.measureStartup(
    packageName = "mypackage.myapp",
    metrics = listOf(StartupTimingMetric()),
    iterations = 5,
    startupMode = StartupMode.COLD
) {
    pressHome()
    startActivityAndWait(Intent().apply {
        action = "mypackage.myapp.myaction"
    })
}

As part of the results, Macrobenchmark produces trace files that you can view in Android Studio to pinpoint performance problems for analysis and debugging.

Benchmark Macrobenchmark
Measure individual functions Measure high-level entry points (for example, activity launch or scrolling a list)
In-process test of CPU work Out-of-process test of full app
Fast iteration speed (often less than 10 seconds) Medium iteration speed (often greater than a minute)
Optional method sampling and tracing Results come with profiling traces
Min API 14 Min API 23