blob: 029f8f509135e9be2e5bfcce11353ce43bfe06e9 [file] [log] [blame] [view]
AndroidX Core Team3cc85e482024-04-15 09:30:13 -07001# MACRObenchmarking in AndroidX
AndroidX Core Team0e7745f2021-04-08 17:00:10 +00002
3[TOC]
4
5<!-- Copied from macrobenchmark docs -->
6
7<table>
8 <tr>
AndroidX Core Teame6150712023-08-03 11:06:01 -07009 <td><strong>Macrobenchmark</strong></td>
10 <td><strong>Benchmark</strong></td>
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000011 </tr>
12 <tr>
AndroidX Core Team3cc85e482024-04-15 09:30:13 -070013 <td>Measure high-level entry points (Activity launch / Scrolling a list)</td>
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000014 <td>Measure individual functions</td>
15 </tr>
16 <tr>
17 <td>Out-of-process test of full app</td>
18 <td>In-process test of CPU work</td>
19 </tr>
20 <tr>
AndroidX Core Team4cc85fa2021-11-23 15:58:34 +000021 <td>Slow iteration speed (Often more than a minute)</td>
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000022 <td>Fast iteration speed (Often less than 10 seconds)</td>
23 </tr>
24 <tr>
AndroidX Core Team3cc85e482024-04-15 09:30:13 -070025 <td>Configure compilation with <a href="https://developer.android.com/reference/androidx/benchmark/macro/CompilationMode">CompilationMode</a></td>
AndroidX Core Teame6150712023-08-03 11:06:01 -070026 <td>Always fully AOT (<code>speed</code>) compiled.</td>
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000027 </tr>
28 <tr>
AndroidX Core Team4cc85fa2021-11-23 15:58:34 +000029 <td>Min API 23</td>
AndroidX Core Team3cc85e482024-04-15 09:30:13 -070030 <td>Min API 19</td>
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000031 </tr>
AndroidX Core Team316a0d92023-08-25 10:53:05 -070032 <tr>
33 <td>Relatively lower stability measurements</td>
34 <td>Higher stability measurements</td>
35 </tr>
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000036</table>
37
38The
AndroidX Core Team9bd4c782021-05-19 14:20:12 -070039[public documentation](https://developer.android.com/studio/profile/macrobenchmark)
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000040for macrobenchmark explains how to use the library. This page focuses on
41specifics to writing library macrobenchmarks in the AndroidX repo. If you're
42looking for measuring CPU perf of individual functions, see the guide for
Ian Baker186108e2023-11-20 06:54:36 -080043MICRObenchmarks [here](/docs/benchmarking.md).
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000044
45### Writing the benchmark
46
47Benchmarks are just regular instrumentation tests! Just use the
AndroidX Core Team316a0d92023-08-25 10:53:05 -070048[`MacrobenchmarkRule`](https://developer.android.com/reference/kotlin/androidx/benchmark/macro/junit4/MacrobenchmarkRule)
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000049provided by the library:
50
51<section class="tabs">
52
53#### Kotlin {.new-tab}
54
55```kotlin
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000056 @get:Rule
57 val benchmarkRule = MacrobenchmarkRule()
58
59 @Test
60 fun startup() = benchmarkRule.measureRepeated(
61 packageName = "mypackage.myapp",
62 metrics = listOf(StartupTimingMetric()),
63 startupMode = StartupMode.COLD,
AndroidX Core Teame6150712023-08-03 11:06:01 -070064 iterations = 10
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000065 ) { // this = MacrobenchmarkScope
66 pressHome()
67 val intent = Intent()
68 intent.setPackage("mypackage.myapp")
69 intent.setAction("mypackage.myapp.myaction")
70 startActivityAndWait(intent)
71 }
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000072```
73
74#### Java {.new-tab}
75
76```java
AndroidX Core Team4cc85fa2021-11-23 15:58:34 +000077 @Rule
78 public MacrobenchmarkRule mBenchmarkRule = MacrobenchmarkRule()
79
80 @Test
81 public void startup() {
82 mBenchmarkRule.measureRepeated(
83 "mypackage.myapp",
84 Collections.singletonList(new StartupTimingMetric()),
85 StartupMode.COLD,
AndroidX Core Teame6150712023-08-03 11:06:01 -070086 /* iterations = */ 10,
AndroidX Core Team4cc85fa2021-11-23 15:58:34 +000087 scope -> {
88 scope.pressHome();
89 Intent intent = Intent();
90 intent.setPackage("mypackage.myapp");
91 intent.setAction("mypackage.myapp.myaction");
92 scope.startActivityAndWait(intent);
93 return Unit.INSTANCE;
94 }
95 );
96 }
AndroidX Core Team0e7745f2021-04-08 17:00:10 +000097```
98
99</section>
100
101## Project structure
102
103As in the public documentation, macrobenchmarks in the AndroidX repo are
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700104comprised of an app, and a separate macrobenchmark test module. In the AndroidX
105repository, there are additional requirements:
AndroidX Core Team0e7745f2021-04-08 17:00:10 +0000106
AndroidX Core Team11f74f72024-09-27 08:53:22 -07001071. Macrobenchmark test module path in `settings.gradle` **must** end with
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700108 `macrobenchmark` to run in CI.
AndroidX Core Team0e7745f2021-04-08 17:00:10 +0000109
AndroidX Core Team11f74f72024-09-27 08:53:22 -07001101. Macrobenchmark target module path in `settings.gradle` **should** end with
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700111 `macrobenchmark-target` to follow convention.
AndroidX Core Team0e7745f2021-04-08 17:00:10 +0000112
AndroidX Core Team11f74f72024-09-27 08:53:22 -07001131. Macrobenchmark modules **must** use project dependencies where available (so
114 `implementation(project(":activity:activity-ktx"))` rather than
115 `implementation("androidx.activity:activity-ktx:1.5.0")`). This prevents
116 accidentally testing against out-of-date versions, and increases coverage of
117 lower level libraries.
118
1191. Each library group **must** declare its own in-group macrobenchmark test and
120 app module, with out using these modules for anything else (e.g. samples).
121 We want to be intentional about which changes affect measurements. More than
122 one of either is allowed, which is sometimes necessary to compare different
123 startup behaviors, see e.g.
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700124 `:emoji2:integration-tests:init-<disabled/enabled>-macrobenchmark-target`.
125 Note that comparing multiple app variants are not currently supported by CI.
AndroidX Core Team0e7745f2021-04-08 17:00:10 +0000126
127Compose Macrobenchmark Examples:
128
129* [`:compose:integration-tests:macrobenchmark-target`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/integration-tests/macrobenchmark-target/)
130
131* [`:compose:integration-tests:macrobenchmark`](https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/integration-tests/macrobenchmark/)
132
AndroidX Core Team3cc85e482024-04-15 09:30:13 -0700133Note: Compose macrobenchmarks are ideally duplicated with View system
AndroidX Core Team0e7745f2021-04-08 17:00:10 +0000134counterparts, defined in `:benchmark:integration-tests:macrobenchmark-target`.
135This is how we compare performance of the two systems.
AndroidX Core Team6146a742022-09-26 09:45:06 -0700136
137### Setup checklist
138
139<table>
140 <tr>
141 <td><strong>Did you setup...</strong></td>
142 <td><strong>Required setup</strong></td>
143 </tr>
144 <tr>
AndroidX Core Teame6150712023-08-03 11:06:01 -0700145 <td>Two modules in <code>settings.gradle</code></td>
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700146 <td>Both the macrobenchmark and target must be added for your group</td>
AndroidX Core Team6146a742022-09-26 09:45:06 -0700147 </tr>
148 <tr>
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700149 <td>The module name for the benchmark (<code>com.android.test</code>) module</td>
150 <td>Must end with <code>macrobenchmark</code></td>
AndroidX Core Team6146a742022-09-26 09:45:06 -0700151 </tr>
152 <tr>
AndroidX Core Team316a0d92023-08-25 10:53:05 -0700153 <td>The module name for the app (<code>com.android.app</code>) module</td>
154 <td>Must end with <code>macrobenchmark-target</code></td>
AndroidX Core Team6146a742022-09-26 09:45:06 -0700155 </tr>
156 <tr>
157 <td>Name the test class in a discoverable way</td>
158 <td>Test classes should have standalone names for easy discovery in the
159 web UI. E.g EmojiStartupTest instead of StartupTest.</td>
160 </tr>
161</table>