What’s new in Android Performance — Google I/O 2023 edition
Over the past years we have worked to make working with performance more approachable and rewarding. In this article we share the latest developments in that area. We’ll cover Baseline Profiles, tooling improvements within Android Studio, libraries and how we made the technology work better for you behind the scenes. We’re also very excited to share new experimental technology, working on top of Baseline Profiles, to provide you with even bigger startup performance improvements. Read on for a full tour of what’s new in Android Performance during Google I/O 2023, or jump directly to the end for actionable steps in your performance journey.
Updates on Baseline Profiles
Baseline Profiles improve code execution speed by about 30 %, for both app startup and runtime by avoiding just-in-time (JIT) compilation. We built several tools to help you streamline Baseline Profile creation and maintenance, including a new Android Studio Template and the Baseline Profile Gradle plugin. You can get started with both today, using Android Studio Hedgehog and the Android Gradle Plugin 8.0.0 or newer.
Streamline profile generation with the Baseline Profile Gradle Plugin
The Baseline Profile Gradle Plugin makes it easier to generate and maintain Baseline Profiles both during local development as well as CI. It performs all the necessary steps to generate and install a Baseline Profile into your application module.
To use the plugin, add an instrumented test module to your project and define a set of tests that navigate through your app to simulate critical user journeys. When you run the instrumented test, the Baseline Profile Gradle Plugin tracks all classes and methods that are executed during these user journeys and generates a Baseline Profile based on these classes and methods. It then copies the generated Baseline Profile into the application module’s source-set.
After applying the plugin, it can be configured with a new
baselineProfile block in your build script. The
generateBaselineProfile Gradle task runs all baseline profile tests for you. The resulting profile files are stored in a generated folder and can be accessed from there. These features remove friction from automating Baseline Profile generation, both locally and on a remote CI server. And by specifying a Gradle Managed Device to use when generating a profile, you don’t even need an attached physical device. The plugin’s DSL enables a highly configurable setup and enables you to automate and reproduce Baseline Profile generation.
Create and manage multiple Baseline Profile source files with AGP 8+
AGP 8 onwards supports easier generation of Baseline Profile with support for multiple source files, variant specific profiles, and support for the new Gradle plugin mentioned above. The default location for Baseline Profiles now is
src/main/baselineProfiles/. Baseline Profile source files stored in this directory will be picked up and merged into your application. This enables you to store separate profile files for app startup and each distinct user journey.
Easier onboarding with the Android Studio Baseline Profile Generator Template
To assist you getting started with Baseline Profiles, Android Studio Hedgehog (2023.1.1) adds the Baseline Profile Generator module wizard template. By using this template, your app can be set up with Baseline Profiles in a visually assisted way.
Get started by navigating to File > New > New Module and select Baseline Profile Generator from the list of templates.
When you’re finished, the template will have made several changes for you. It creates a new
:baselineprofile test module containing basic generators and benchmarks. The
BaselineProfileGenerator class creates a basic baseline profile for you and
StartupBenchmarks can verify everything works as intended. Also, Baseline Profile Gradle plugin will be applied in relevant modules. Lastly, a dependency on
androidx.profileinstaller will be added, to aid local verification and backwards compatibility.
From here, all you need to do is execute the Generate Baseline Profile run configuration, which runs included Baseline Profile generators and copies the generated profiles to
The run configuration calls the
:app:generateBaselineProfile task, looks for all Baseline Profiles generators and only runs these.
BaselineProfileGenerator is very basic and does only start your app and wait for the app startup to complete. We recommend creating a Baseline Profile for each critical user journey through your app. As user journeys vary between apps, it’s up to you to decide what to optimize. A good starting point is anything that’s directly tied to business results, such as sign up, login, checkout or other major actions your app offers. You can get inspiration from our code samples.
To get started, download Android Studio Hedgehog Canary today.
And for a guided tour through the whole onboarding process check out the updated codelab: Improve app performance with Baseline Profiles.
Introducing Startup Profiles and Dex layout optimizations
Starting with version 8.1, the Android Gradle Plugin (AGP) can pull code that’s required for app startup into the primary dex file of your app. This optimization is called dex layout optimization and helps to reduce dex page faults during app startup. This can significantly speed up app startup as only a single dex file needs to be loaded until the app has completed startup.
While AGP can create separate dex files for your app, it doesn’t know what fully defines startup for your app without your help. This is where Startup Profiles come in. You can think of Startup Profiles as a subset of Baseline Profiles that are specifically tailored to app startup. Both share the same format and use the same underlying technology. Since app startup differs for every application, libraries do not contribute to the Startup Profile.
Baseline Profiles provide performance gains of around 30 %, compared to an app that requires interpretation and JIT compilation, for example right after an update is pushed. Our early tests with Dex layout optimizations have shown an additional 30% performance improvement on top of Baseline Profile gains for app startup. This is especially beneficial since these gains are always seen in cold startups, even if your production app already has a well functioning cloud profile.
To make the most of Dex layout optimizations and Startup Profiles, you need to let the Android Framework know when your app is done with startup. If you don’t do anything, app startup will be considered done when the first frame is drawn. To make sure the Startup Profile contains information up to the point where your user can take over, use the
reportFullyDrawn APIs. You can do this via the
FullyDrawnReporter or the Compose
ReportDrawn APIs. Additionally, you need to define the end point for the startup benchmark at a point where you deem startup complete. Match the call to
reportFullyDrawn with what you’re expecting to be displayed on screen at the point where the app is ready to be used.
You can read more about Dex layout optimizations and Startup profiles in the guiding documentation.
New developments in the Macrobenchmark library
The Macrobenchmark library enables you to measure app performance, create baseline profiles and monitor whether changes to your app make a difference to app performance. The 1.2.0 will graduate to a beta release soon. Here are some feature highlights.
Utilizing new Android platform features in benchmarks
From Android 13 and newer you can generate a Baseline Profile with the
BaselineProfileRule on non-rooted devices or emulators.
From Android 14 and newer, target apps no longer need to be reinstalled between benchmark runs. This enables apps to save state, such as cache, session state or login tokens between runs. This change removes the need to inject these states manually before benchmarking, which would have required a rooted device.
✨ Baseline Profile generation is no longer considered experimental ✨
You can remove the opt-in to experimental API annotation from your code when creating a baseline profile using the
collectBaselineProfile method. But if you like to stay on experimental APIs, we have a new API for your consideration.
The newly introduced
collectStableBaselineProfile runs and waits until a profile is considered stable for a given amount of iterations. This means that your app’s Baseline Profile will better reflect what’s going on in your app as a code path is executed.
More powerful metrics with custom trace processing
PerfettoTraceRule enables custom trace collection in tests other than benchmarks (requires API 23+). This is a powerful feature that will allow users to collect performance and timing data about tests.
PerfettoTraceProcessor enables querying trace contents, and is the engine behind all of the existing Macrobenchmark Metric APIs. Now it’s possible to use it with
TraceMetric to define fully custom metrics in the same way Macrobenchmark does from anything information in a Perfetto system trace.. This is another powerful feature that will allow users to customize their benchmarks even further.
Attributing Power consumption from benchmarks
PowerMetric API can be used to measure energy consumption and power states. This is a useful feature that will allow users to track the energy consumption of their benchmarks.
Bug fixes and other improvements
The team behind Macrobenchmark also made a variety of other improvements to ergonomics, fixed bugs and improved overall behavior. To learn more, check out the documentation. If you want to get more detail, you can find a full list of release notes with attached code and tracking issues here.
Android Studio Power Profiler
Android Studio Hedgehog features a new Profiler which shows power consumption on physical devices, segmented by each sub-system (such as: Camera, GPS, and more). This data is made available when recording a System Trace and helps you to visually correlate power consumption of the device to the actions happening in your app. For example, you can A/B test batching API calls vs making individual API calls to optimize power consumption in the Cellular power rail.
To get started, use a Pixel 6+ device to record a System trace and load it into Android Studio, or use the profiler to capture a System trace directly from the attached device.
Why you should focus on performance
When working on application performance, finding the right starting point can be a challenge. Working with the Android developer community, we found that engineers sometimes lack the right information to justify working on app performance.
Improving performance has a number of benefits, both for your users and for your business. For users, a fast and responsive app means a better user experience. Your users will be able to get the information they need quickly and easily, and they’ll be more likely to come back to your app.
For your business, improved performance can lead to increased revenue and decreased costs. When users are happy with your app, they’re more likely to make purchases or take other actions that benefit your business. Additionally, a well-performing app can help you save money on development and maintenance costs.
- Set your app up to use Baseline Profiles with the new Gradle plugin
- Upgrade to Android Gradle Plugin 8+
- Move existing Baseline Profiles into the new default directory
- Download the Android Studio Hedgehog Canary to check out the Baseline Profile template and power profiler
- Check out our updated codelab for a guided tour
- Use the Fully Drawn and
collectStableBaselineProfileAPIs for better Baseline Profiles
- Get started with Dex layout optimizations for even more performance gains
- Implement your own Macrobenchmark tests to measure how performance moves over time
- Record a System trace on a Pixel 6+ device to view power consumption of different subsystems (Camera, GPS, CPU, etc)
- 👏 and share this article to help improve app performance for everyone