The Baseline Profile Gradle plugin makes it easier to generate and maintain Baseline Profiles. It helps you do the following tasks:
- Create new Baseline Profiles for your app.
- Create new Baseline Profiles for your library.
- Customize your Baseline Profile generation.
This page explains how to use the Baseline Profile Gradle plugin to customize the generation of your Baseline Profiles.
Plugin requirements
- AGP 8.0 or higher
- Dependency on the latest Gradle plugin version
Use a Gradle Managed Devices to generate Baseline Profiles
To use a Gradle Managed Device (GMD) to
generate your Baseline Profile, add one in the build.gradle.kts
configuration
of the profile producer module—likely the :baselineprofile
test module—as
shown in the following example:
Kotlin
android { testOptions.managedDevices.devices { create<com.android.build.api.dsl.ManagedVirtualDevice>("pixel6Api31") { device = "Pixel 6" apiLevel = 31 systemImageSource = "aosp" } } }
Groovy
android { testOptions.managedDevices.devices { pixel6Api31(ManagedVirtualDevice) { device 'Pixel 6' apiLevel = 31 systemImageSource 'aosp' } } }
Use the GMD to generate Baseline Profiles by adding it to the Baseline Profile
Gradle plugin configuration as follows, in the build.gradle.kts
of the
:baselineprofile
test module:
Kotlin
baselineProfile { managedDevices += "pixel6Api31" }
Groovy
baselineProfile { managedDevices = ['pixel6Api31'] }
When you use a GMD to generate Baseline Profiles, set useConnectedDevices
to
false
, in your :baselineprofile
test module:
Kotlin
baselineProfile { ... useConnectedDevices = false }
Groovy
baselineProfile { ... useConnectedDevices false }
Generate Baseline Profiles for different variants
You can generate Baseline Profiles per variant, per flavor, or as a single file
to utilize for all variants. Control this behavior through the merge setting, as
shown in the following example, in the build.gradle.kts
of the
application or library module.
Kotlin
baselineProfile { mergeIntoMain = true }
Groovy
baselineProfile { mergeIntoMain true }
To merge the generated profiles for all variants into a single profile, set
mergeIntoMain
to true
. It isn't possible to generate per-variant Baseline
Profiles when this setting is true
, so there's a single Gradle task called
generateBaselineProfile
. The profile is output at
src/main/generated/baselineProfiles
.
To disable merging and have one profile per variant, set mergeIntoMain
to
false
. In this case, multiple variant-specific Gradle tasks exist. For
example, when there are two flavors—such as free and paid—and one
release build type, the tasks are the following:
* `generateFreeReleaseBaselineProfile`
* `generatePaidReleaseBaselineProfile`
* `generateReleaseBaselineProfile`
To specify the merging behavior per variant, use the following code:
Kotlin
baselineProfile { variants { freeRelease { mergeIntoMain = true } } }
Groovy
baselineProfile { variants { freeRelease { mergeIntoMain true } } }
In the preceding example, the variants where the flag is set to true
are all
merged into src/main/generated/baselineProfiles
, while the profiles for the
variants where the flag is set to false
are kept in the folder
src/<variant>/generated/baselineProfiles
.
By default, mergeIntoMain
is set to true
for libraries and false
for apps.
Automatically generate Baseline Profiles when assembling a new release
You can configure Baseline Profiles to automatically generate with every release
build, instead of manually using the task generateBaselineProfile
. With
automatic generation, the most updated profile is included in the release build.
To enable automatic generation for release builds, use the
automaticGenerationDuringBuild
flag:
Kotlin
baselineProfile { automaticGenerationDuringBuild = true }
Groovy
baselineProfile { automaticGenerationDuringBuild true }
Setting the automaticGenerationDuringBuild
flag to true
triggers the
generation of a new Baseline Profile for each release assembly. This means that
running an assemble release build task, such as ./gradlew:app:assembleRelease
,
also triggers :app:generateReleaseBaselineProfile
, starts the Baseline Profile
instrumentation tests, and builds the Baseline Profile build on which they run.
While automatic generation helps users gain the best performance benefit, it
also increases the build time because of the double build and instrumentation
tests.
You can also specify this behavior per variant, as shown in the following example:
Kotlin
baselineProfile { variants { freeRelease { automaticGenerationDuringBuild = true } } }
Groovy
baselineProfile { variants { freeRelease { automaticGenerationDuringBuild true } } }
In the preceding example, the task generateFreeReleaseBaselineProfile
runs
when starting assembleFreeRelease
. This helps when the user wants to have, for
example, a release
for distribution build that always generates the profile
when building, and a releaseWithoutProfile
build for internal testing.
Store Baseline Profiles into sources
You can store Baseline Profiles in the source directory through the saveInSrc
flag in the build.gradle.kts
of the application or library module:
true
: the Baseline Profile is stored insrc/<variant>/generated/baselineProfiles
. This lets you commit the latest generated profile with your sources.false
: the Baseline Profile is stored in the intermediate files in the build directory. This way, when committing your code, you don't save the latest generated profile.
Kotlin
baselineProfile { saveInSrc = true }
Groovy
baselineProfile { saveInSrc true }
You can also specify this behavior per variant:
Kotlin
baselineProfile { variants { freeRelease { saveInSrc = true } } }
Groovy
baselineProfile { variants { freeRelease { saveInSrc true } } }
Filter profile rules
The Baseline Profile Gradle plugin lets you filter the Baseline Profile rules generated. This is particularly helpful for libraries, if you want to exclude profile rules for classes and methods that are part of other dependencies of the sample app or the library itself. The filters can include and exclude specific packages and classes. When you only specify excludes, only matching Baseline Profile rules are excluded and everything else is included.
The filters specification can be any of the following:
- Package name ending with double wildcards to match the specified package and
all subpackages. For example,
com.example.**
matchescom.example.method
andcom.example.method.bar
. - Package name ending with wildcard to match specified package only. For
example,
com.example.*
matchescom.example.method
but doesn't matchcom.example.method.bar
. - Class names to match a specific class—for example,
com.example.MyClass
.
The following examples show how to include and exclude specific packages:
Kotlin
baselineProfile { filter { include("com.somelibrary.widget.grid.**") exclude("com.somelibrary.widget.grid.debug.**") include("com.somelibrary.widget.list.**") exclude("com.somelibrary.widget.list.debug.**") include("com.somelibrary.widget.text.**") exclude("com.somelibrary.widget.text.debug.**") } }
Groovy
baselineProfile { filter { include 'com.somelibrary.widget.grid.**' exclude 'com.somelibrary.widget.grid.debug.**' include 'com.somelibrary.widget.list.**' exclude 'com.somelibrary.widget.list.debug.**' include 'com.somelibrary.widget.text.**' exclude 'com.somelibrary.widget.text.debug.**' } }
Customize the filter rules for different variants as follows:
Kotlin
// Non-specific filters applied to all the variants. baselineProfile { filter { include("com.myapp.**") } } // Flavor-specific filters. baselineProfile { variants { free { filter { include("com.myapp.free.**") } } paid { filter { include("com.myapp.paid.**") } } } } // Build-type-specific filters. baselineProfile { variants { release { filter { include("com.myapp.**") } } } } // Variant-specific filters. baselineProfile { variants { freeRelease { filter { include("com.myapp.**") } } } }
Groovy
// Non-specific filters applied to all the variants. baselineProfile { filter { include 'com.myapp.**' } } // Flavor-specific filters. baselineProfile { variants { free { filter { include 'com.myapp.free.**' } } paid { filter { include 'com.myapp.paid.**' } } } } // Build-type specific filters. baselineProfile { variants { release { filter { include 'com.myapp.**' } } } } // Variant-specific filters. baselineProfile { variants { freeRelease { filter { include 'com.myapp.**' } } } }
You can also filter rules using the filterPredicate
argument in BaselineProfileRule.collect()
, but we recommend using the Gradle
plugin to filter because it provides a simpler way to filter subpackages and a
single place to configure the entire module.
Customize benchmark and Baseline Profile build types
The Baseline Profile Gradle plugin creates additional build types to generate
the profiles and to run benchmarks. These build types are prefixed with
benchmark
and nonMinified
. For example, for the release
build type, the
plugin creates the benchmarkRelease
and nonMinifiedRelease
build types.
These build types are automatically configured for the specific use case and
don't generally need any customization. But there are some cases in which it
might still be useful to apply some custom options, for example to apply a
different signing config.
You can customize the automatically generated build types using a subset of build type properties; properties that aren't usable are overridden. The following example shows how to customize the additional build types and which properties are overridden:
Kotlin
android { buildTypes { release { ... } create("benchmarkRelease") { // Customize properties for the `benchmarkRelease` build type here. // For example, you can change the signing config (by default // it's the same as for the `release` build type). signingConfig = signingConfigs.getByName("benchmarkRelease") } create("nonMinifiedRelease") { // Customize properties for the `nonMinifiedRelease` build type here. signingConfig = signingConfigs.getByName("nonMinifiedRelease") // From Baseline Profile Gradle plugin 1.2.4 and higher, you can't // customize the following properties, which are always overridden to // avoid breaking Baseline Profile generation: // // isJniDebuggable = false // isDebuggable = false // isMinifyEnabled = false // isShrinkResources = false // isProfileable = true // enableAndroidTestCoverage = false // enableUnitTestCoverage = false } } }
Groovy
android { buildTypes { release { ... } benchmarkRelease { // Customize properties for the `benchmarkRelease` build type here. // For example, you can change the signing config (by default it's the // same as for the `release` build type.) signingConfig = signingConfigs.benchmarkRelease } nonMinifiedRelease { // Customize properties for the `nonMinifiedRelease` build type here. signingConfig = signingConfigs.nonMinifiedRelease // From Baseline Profile Gradle plugin 1.2.4 and higher, you can't use // the following properties, which are always overridden to avoid breaking // Baseline Profile generation: // // isJniDebuggable = false // isDebuggable = false // isMinifyEnabled = false // isShrinkResources = false // isProfileable = true // enableAndroidTestCoverage = false // enableUnitTestCoverage = false } } }
Additional notes
When creating Baseline Profiles, here are some additional things to be aware of:
Compiled Baseline Profiles must be smaller than 1.5 MB. This doesn't apply to the text format in your source files, which are typically much larger prior to compilation. Verify the size of your binary Baseline Profile by locating it in the output artifact under
assets/dexopt/baseline.prof
for APK orBUNDLE-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, don't worry about this. However, depending on your app and the size and number of journeys, adding a lot of journeys can result in suboptimal performance. Test the performance of your app by trying different profiles and verifying that the performance doesn't regress after the additions.