element-android
element-android copied to clipboard
Baseline and Startup Profiles
Type of change
- [x] Feature
- [ ] Bugfix
- [x] Technical
- [ ] Other :
Content
Adding the Baseline and Startup profiles generation module and actually generated profiles.
Motivation and context
Both Baseline and Startup profiles provide relatively cheap boosting of cold app starting:
- Baseline profiles tell the OS to precompile critical parts of the app ahead of time
- Startup profiles affect dex file creating during app building, putting the startup-related code into the single first dex file
Nowadays creating of these profiles is mostly automated by Androidx's Baseline Profile Gradle Plugin. Android Studio has a template for a standalone Gradle module, which encapsulates the majority of BP management logic. The generating of the profiles can be done automatically with emulators as Gradle Managed Devices, but the benchmarking is highly recommended to perform on physical devices.
This PR consists of:
- The
:baselineprofilemodule, generated from the template with almost no tweaks. The only focus for improvement was the startup time. Other critical flows can be improved the same way, but are outside of the scope of this PR. The module provides a way for BP generation and benchmarking; - Actually the generated profiles. These are the plain text files, which are rather big. When they are compiled and put into APKs, they are a few kilobytes in size. Profiles are generated for each 'release' build type, specifically:
fdroidRelease,gplayReleaseandgplayNightly.
During the integration it turned out that BP had a lot of raw edges. There were some critical issues affecting the integration into Element app:
- https://issuetracker.google.com/issues/307784512
- https://issuetracker.google.com/issues/324837887
- https://issuetracker.google.com/issues/361370179
- And some others
These issueas are fixed by now and the only sustainable minimum versions of tools which provide adequate experience are:
- Android Gradle Plugin 8.7.0-alpha09 (the PR sets it as 8.7.1)
- Baseline Profile Gradle Plugin (comes from androidx.benchmark) 1.3.1 (1.3.3 in this PR)
- ProfileInstaller 1.4.0 (1.4.1 in this PR)
Yes, some issues come from AGP itself, so it is updated. Minor build scripts' changes were done because of it.
How exactly does this PR improve the startup time?
The numbers highly depend on a physical device used for benchmarks and the state such a device is in. Tests done right after a reboot show better results than in case when a device works for days and have many apps running in a background. Some devices won't run benchmark tests at all (some Oneplus devices).
I used several devices for benchmarking:
| Device | OS version | Startup time diff |
|---|---|---|
| Oneplus 8T | Android 14 | -8% |
| Samsung S20 FE 5G | Android 13 | -12% |
| Samsung Galaxy Tab A7 | Android 12 | -22% |
Actual benchmark results:
Oneplus 8T
Samsung S20 FE 5G
Samsung Galaxy Tab A7
How can the profiles be generated?
With a simple command: ./gradlew :vector-app:generateBaselineProfile.
The process uses Gradle Managed Devices to use a specific android emulator (Pixel 6, API 34), so no active emulator or physical device is required for profile generation.
What are the cons?
- Although the PR already gives some startup time decreasing, it is recommended to make further adjustments of BP generation code according to critical flows of the app in order to gain the full power of BP;
- If some new functionality becomes a part of the app startup, the BP becomes slightly stale. It is recommended to generate new BP in such a case and commit them. Or automate this process in various known ways. Could be discussed separately, I have several options;
- The fact that BP contain non obfuscated code paths isn't an issue at all. The BP are considered during the work of R8, so the compiled BP are done according to the obfuscaiton step;
- The
srcdirectory cluttering: these directories contain actual BP and slightly hinder the persepiton of the immediate children ofsrc; - The debug google-services.json file was duplicated 2 times, since the Play Services Gradle Plugin can't properly pick the same file from another build type.
Tested devices
- [x] Physical (for benchmarking): API 31, 33, 34
- [x] Emulator (for profiles generating): API 34
Checklist
- [x] Changes has been tested on an Android device or Android emulator with API 21
- [ ] UI change has been tested on both light and dark themes
- [ ] Accessibility has been taken into account. See https://github.com/element-hq/element-android/blob/develop/CONTRIBUTING.md#accessibility
- [x] Pull request is based on the develop branch
- [x] Pull request includes a new file under ./changelog.d. See https://github.com/element-hq/element-android/blob/develop/CONTRIBUTING.md#changelog
- [ ] Pull request includes screenshots or videos if containing UI changes
- [x] Pull request includes a sign off (in the last commit)
- [x] You've made a self review of your PR
- [ ] If you have modified the screen flow, or added new screens to the application, you have updated the test UiAllScreensSanityTest.allScreensTest()
~Keeping on hold due to certain issues with AGP and Baseline Profile gradle plugin. Specifically:~
- ~https://issuetracker.google.com/issues/307784512~
- ~https://issuetracker.google.com/issues/324837887 (not really fixed in the latest 1.3.0-rc01)~
Hello @bmarty , Could you have a look at this PR?
Hi @bmarty, @BillCarsonFr
Could you please have a look at this PR? I forgot setting element-android-reviewers as a reviewer while creating the PR and it doesn't seem possible to set it after the PR is created.
It would be nice to have this feature discussed/integrated into Element Android. After that I would look into integrating the same thing for Element X Android.