Create Baseline Profiles

As an app developer, you can automatically generate profiles for every app release by using the Jetpack Macrobenchmark library and BaselineProfileRule. It is recommended to use com.android.tools.build:gradle:7.3.1 or higher, which comes with build improvements when using Baseline Profiles.

Define Baseline Profile generator

To create Baseline Profiles using the Macrobenchmark library:

  1. Set up a Macrobenchmark module in your Gradle project.

  2. Define a new test called BaselineProfileGenerator that looks something like:

    @OptIn(ExperimentalBaselineProfilesApi::class)
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collectBaselineProfile(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }
    

    The generator can contain interactions with your app beyond app startup. This lets you optimize runtime performance of your app, such as scrolling lists, running animations, navigating within an Activity, and others. View some other examples on tests that use @BaselineProfileRule to improve critical user journeys.

  3. (Optional) You must disable obfuscation when generating Baseline Profiles. You can do it by creating another Proguard file in your app module and adding -dontobfuscate, only for your benchmark build type that is responsible for generating the profiles.

    Kotlin

    buildTypes {
        val benchmark by creating {
            // Only use benchmark proguard rules
            proguardFiles("benchmark-rules.pro")
            // ...
        }
    }
    

    Groovy

    buildTypes {
        benchmark {
            // Only use benchmark proguard rules
            proguardFiles 'benchmark-rules.pro'
            // ...
        }
    }
    

Generate the Baseline Profile

  1. Run the generator as an instrumented test on a rooted physical device, emulator, or Gradle managed device. To set up a managed device, open your build.gradle.kts file and within the testOptions configuration block, add managedDevices, devices, and create your definition of an emulator. Make sure to use aosp as the systemImageSource because you need root access for the Baseline Profile generator.

    Kotlin

    testOptions {
        managedDevices {
            devices {
                create ("pixel6Api31", ManageVirtualDevice::class) {
                    device = "Pixel 6"
                    apiLevel = 31
                    systemImageSource = "aosp"
                }
            }
        }
    }
    

    Groovy

    testOptions {
        managedDevices {
            devices {
                pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                    device = "Pixel 6"
                    apiLevel = 31
                    systemImageSource = "aosp"
                }
            }
        }
    }
    
  2. Gradle creates the required tasks based on the selected device name and the build variants available in the module. It is formatted as [emulator_name][flavor][build type]AndroidTest. This task can be executed from a terminal like this, :

    ./gradlew :benchmark:pixel6Api31BenchmarkAndroidTest
    

Apply the generated rules

The Baseline Profile generator creates a human readable text file (HRF) on the device and also copies it into your host machine. Follow these steps to apply the generated profile to your code:

  1. Locate it in build folder of the module you generated the profile in: [module]/build/outputs/managed_device_android_test_additional_output/[device].

    Profiles follow the [class name]-[test method name]-baseline-prof.txt naming pattern, which looks like this: BaselineProfileGenerator-startup-baseline-prof.txt.

  2. Copy the generated profile to src/main/ of your app module, alongside your AndroidManifest.xml and rename the file to baseline-prof.txt.

  3. Add a dependency to the ProfileInstaller library in your app's build.gradle to enable local Baseline Profile compilation where Cloud Profiles aren't available. This is the only way to sideload a Baseline Profile locally.

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.2.0")
    }
    
  4. Build the production version of your app, during which the applied HRF rules are compressed into binary form and included in the APK or AAB. Then distribute your app as usual.

Additional notes

When creating Baseline Profiles, there are some additional things to note:

  • Binary Baseline Profiles must be smaller than 1.5 MB. You can verify the size of your baseline profile by locating it in the output artifact under assets/dexopt/baseline.prof for APK or BUNDLE-METADATA/com.android.tools.build.profiles/baseline.prof for AAB.

  • Broad rules that compile too much of the application can slow down startup due to increased disk access. If you're just starting with Baseline Profiles, you don't need to worry about it. But when you start adding a lot1 of journeys, you should test the performance of your app by trying different profiles and verifying the performance doesn't regress with the additions.


  1. Depending on your app size and the number journeys.