You can identify potential bottlenecks and improve overall app performance by
recording device activity over a short period of time and [collecting traces of
your app's startup period](https://developer.android.com/topic/performance/tracing). This page shows how to
set up your environment for performance testing.

## Use the Macrobenchmark library

The [Macrobenchmark
library](https://developer.android.com/topic/performance/benchmarking/macrobenchmark-overview) measures
larger end-user interactions, such as startup, interacting with the UI, and
animations. The library provides direct control over the performance environment
you're testing. It lets you control compiling, starting, and stopping your app
to directly measure precise app startup time. It also works to minimize the
noise and differences between test runs.

## Use mid-range devices to identify potential performance issues

Test performance on each device type you care about. High-end devices with fast
components can hide performance problems on earlier, slower, or low RAM devices.
Lower-end devices can take longer to load data or run code, making it easier to
identify bottlenecks. Optimizing performance for low-end devices usually also
benefits optimization for high-end devices.

## Reduce noise

- Network: test your apps or processes with strong and stable internet Wi-Fi speeds. If the app startup time includes a network request, note this as a place where variability might occur.
- RAM usage: don't have any other apps running in the background of your device while testing app startup performance.
- Battery: ensure your device is charged to avoid any hardware-specific low power performance throttling.

## Test on release builds

Use release builds to test performance. Debug builds are [unsuitable for
performance
debugging](https://developer.android.com/studio/profile/measuring-performance#apk-considerations), as they
don't provide compilation optimization and significantly impact performance.

However, it's okay to use an unobfuscated release build to identify classes and
operation names. Specifically, we recommend enabling [minify
(R8)](https://developer.android.com/studio/build/shrink-code) and disabling obfuscation, with
[`-dontobfuscate`](https://developer.android.com/studio/build/shrink-code#obfuscate) in the proguard file.
It's easier to identify layouts, assets, and resources if the build is
unobfuscated.

Make sure you include the
[profileable](https://developer.android.com/guide/topics/manifest/profileable-element) flag in the manifest
so that your custom events are visible in non-debuggable builds. This flag is
available on Android 10 (API level 29) and later.

## Add custom traces to your app operations

Add [custom traces](https://developer.android.com/topic/performance/tracing/custom-events) within your app to
make it easier to identify what operations are performed by your app compared to
other libraries. This helps give you more context about what the app is doing at
all times.