Mobile Development 29 min read

Custom Baseline Profiles Optimization for Android Apps: Design, Implementation, and Evaluation

This article describes the background of Android code execution, the evolution from full AOT to JIT+AOT and Cloud Profiles, the limitations of Google Baseline Profiles, and presents a custom Gradle‑based solution that generates baseline.prof files for all AGP versions, integrates with the installation pipeline, collaborates with OEMs, and demonstrates measurable cold‑start improvements.

Watermelon Video Tech Team
Watermelon Video Tech Team
Watermelon Video Tech Team
Custom Baseline Profiles Optimization for Android Apps: Design, Implementation, and Evaluation

Background

On Android, Java/Kotlin code is compiled to DEX bytecode and interpreted at runtime, which is slow. Android 5 introduced full AOT compilation during installation, but it caused long install times and large disk usage. Starting with Android 7, a hybrid JIT+AOT model was adopted, and Android 9 added Cloud Profiles to collect hot methods from early adopters. In 2022 Google released Baseline Profiles, allowing developers to ship their own hot‑method lists for install‑time compilation, but the official solution requires AGP 7+, depends on Google Play, and cannot be used in many Chinese devices.

Solution Exploration and Implementation

The custom solution reproduces the official Baseline Profile workflow and adds two main stages:

Hot‑method collection: either run the app on a device or manually create a baseline-prof.txt file.

Compile‑time processing: convert the text file into binary baseline.prof and baseline.profm using the CompileArtProfileTask.kt logic.

Installation‑time processing: embed the binary files into the APK assets and let the system’s ArtManagerService handle them during install.

Hot‑method collection

The official approach uses the Jetpack Macrobenchmark library and BaselineProfileRule . The article shows that the same result can be achieved by invoking the profman command directly:

adb shell profman --dump-classes-and-methods \
    --profile-file=/data/misc/profiles/cur/0/com.example.app/primary.prof \
    --apk=/data/app/com.example.app-XXXX/base.apk > baseline-prof.txt

The generated baseline-prof.txt contains entries such as:

PLcom/example/MyClass;->a(Lcom/example/MyClass;)Ljava/lang/String;
HSPLorg/android/spdy/SpdyAgent;->initSo(Ljava/lang/String;I)Z

Each line follows the [FLAGS][CLASS_DESCRIPTOR]->[METHOD_SIGNATURE] format, where flags H , S , P indicate Hot, Startup, or Post‑Startup methods.

Compile‑time processing

The text file is merged with any baseline‑prof.txt files from AndroidX libraries, then transformed into binary form by the CompileArtProfileTask (implemented in CompileArtProfileTask.kt ). The core steps are:

Read the human‑readable profile.

Apply ProGuard mapping if the APK is obfuscated.

Create ArtProfile and serialize it to baseline.prof and baseline.profm using ArtProfileSerializer .

Installation‑time processing

During install, the system calls ArtManagerService.prepareAppProfiles , which eventually invokes dexopt.cpp#prepare_app_profile . This forks a process that runs profman with file descriptors for the reference profile, the new profile, and the APK:

./profman --reference-profile-file-fd=9 \
    --profile-file-fd=10 --apk-fd=11 \
    --dex-location=/data/app/com.example.app-XXXX/base.apk \
    --copy-and-update-profile-key

The reference profile ( /data/misc/profile/ref/…/primary.prof ) stores the accumulated hot methods for the package; the new baseline.prof is merged into it.

Dex optimization

After profile merging, the PackageDexOptimizer triggers dex2oat with the --profile-file-fd argument. The compiler loads the profile via LoadProfile() , checks hot‑method flags, and only compiles methods marked as hot or startup. The decision is made in ShouldCompileBasedOnProfile :

bool result = profile_compilation_info->IsHotMethod(profile_index, method_ref.index);
return result;

Compiled methods are emitted by CodeGenerator::Compile , and the OatWriter uses the hotness bits to place hot methods early in the OAT file, improving page‑level I/O.

Vendor cooperation

Because install‑time Baseline Profile requires Google Play, the team worked with domestic OEMs (Xiaomi, Huawei, etc.) to enable the feature without Play services. They provided APKs containing the binary profiles, and OEMs adopted strategies such as background compilation after install.

Compression handling

The binary baseline.prof must be stored uncompressed in the APK. The article shows how to write a JarEntry with STORED method, set size and CRC, and verify with unzip -v . The file size impact is negligible (≈62 KB for 70 k hot methods, < 1 % compression).

Optimization results

Testing on devices (Honor Android 11, Xiaomi Android 13) showed cold‑start time reductions of 6.9 % to 12.3 % (e.g., 950 ms → 884 ms). The improvement is measured via the TTID metric using adb shell am start-activity -W .

References & Team

Links to Android documentation, source code, and the ByteDance Xigua Video client team are provided.

PerformanceAndroidJITAOTGradle PluginBaseline ProfilesDex Optimization
Watermelon Video Tech Team
Written by

Watermelon Video Tech Team

Technical practice sharing from Watermelon Video

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.