创建基准配置文件

使用 Jetpack Macrobenchmark 库BaselineProfileRule 可为每个应用版本自动生成配置文件。建议使用 com.android.tools.build:gradle:8.0.0 或更高版本,因为这些版本改进了使用基准配置文件时的构建功能。

创建新基准配置文件的大致步骤如下:

  1. 设置基准配置文件模块。
  2. 定义有助于生成基准配置文件的 JUnit 测试。
  3. 添加想要优化的关键用户历程 (CUJ)。
  4. 生成基准配置文件。

生成基准配置文件后,请使用实体设备对其进行基准测试,以衡量速度方面的改进。

使用 AGP 8.2 或更高版本创建新的基准配置文件

要创建新的基准配置文件,最简单的方式就是使用基准配置文件模块模板,该模板从 Android Studio Iguana 和 Android Gradle 插件 (AGP) 8.2 开始提供。

Android Studio 基准配置文件生成器模块模板会自动创建一个新模块,以便生成基准配置文件并对其进行基准测试。运行该模板会生成大部分典型的 build 配置代码、基准配置文件生成代码,以及验证代码。该模板会创建用于生成基准配置文件并对其进行基准测试的代码,以便衡量应用启动情况。

设置基准配置文件模块

如需运行基准配置文件模块模板,请按以下步骤操作:

  1. 依次选择 File > New > New Module
  2. Templates 面板中选择 Baseline Profile Generator 模板,并对其进行配置:
    图 1. 基准配置文件生成器模块模板。

    该模板中的字段如下:

    • Target application:定义为哪个应用生成基准配置文件。如果项目中只有一个应用模块,此列表中将只有一项。
    • Module name:指定要创建的基准配置文件模块将使用的名称。
    • Package name:指定基准配置文件模块将使用的软件包名称。
    • Language:选择生成的代码是 Kotlin 还是 Java。
    • Build configuration language:选择 build 配置脚本是使用 Kotlin Script (KTS) 还是 Groovy。
  3. 点击 Finish,系统即会创建一个新模块。如果您使用了源代码控制工具,系统可能会提示您将新创建的模块文件添加到源代码控制工具中。

定义基准配置文件生成器

新创建的模块中包含用于生成基准配置文件并对其进行基准测试的测试,以及仅用于测试基本的应用启动情况的测试。建议将这些代码扩充为包含 CUJ 和高级启动工作流。如果您将这些 CUJ 提取到生成的基准配置文件和基准测试代码之外,以便它们可以用于这两者,将有助于提高可维护性。这意味着系统会以一致的方式使用您对 CUJ 所做的更改。

生成并安装基准配置文件

基准配置文件模块模板中添加了一项新的运行配置,用于生成基准配置文件。如果您使用产品变种,Android Studio 会创建多项运行配置,以便您可以为每个变种生成单独的基准配置文件。

图 2. 运行此配置会生成基准配置文件。

Generate Baseline Profile 运行配置在完成运行后,会将生成的基准配置文件复制到要分析的模块中的 src/variant/generated/baselineProfiles/baseline-prof.txt 文件。变体选项要么是发布 build 类型,要么是涉及发布 build 类型的 build 变体。

生成的基准配置文件最初是在 build/outputs 中创建的。完整路径取决于要分析的应用变体或变种,以及您是使用 Gradle 管理的设备还是使用已连接的设备进行分析。如果您使用代码所用的名称和由模板生成的 build 配置,系统会在 build/outputs/managed_device_android_test_additional_output/nonminifiedrelease/pixel6Api31/BaselineProfileGenerator_generate-baseline-prof.txt 文件中创建基准配置文件。您可能不必直接与生成的此版本基准配置文件产生任何交互,除非您手动将其复制到目标模块(不推荐)。

使用 AGP 8.1 创建新的基准配置文件

如果您无法使用基准配置文件模块模板,请使用 Macrobenchmark 模块模板和基准配置文件 Gradle 插件来创建新的基准配置文件。建议针对 Android Studio Giraffe 和 AGP 8.1 以上版本使用这些工具。

如需使用 Macrobenchmark 模块模板和基准配置文件 Gradle 插件创建新的基准配置文件,请执行以下步骤:

  1. 在 Gradle 项目中设置一个 Macrobenchmark 模块
  2. 定义一个名为 BaselineProfileGenerator 的新类:
    class BaselineProfileGenerator {
        @get:Rule
        val baselineProfileRule = BaselineProfileRule()
    
        @Test
        fun startup() = baselineProfileRule.collect(
            packageName = "com.example.app",
            profileBlock = {
                startActivityAndWait()
            }
        )
    }
    

    该生成器可以包含应用启动之外的应用互动。这样,您就可以优化应用的运行时性能,例如滚动列表、运行动画以及在 Activity 内导航时的性能。您可以查看其他的测试示例,了解如何使用 @BaselineProfileRule 改善关键用户历程。

  3. 添加基准配置文件 Gradle 插件 (libs.plugins.androidx.baselineprofile)。使用该插件,您可以更轻松地生成基准配置文件并在将来维护它们。

  4. 如需生成基准配置文件,请在终端运行 :app:generateBaselineProfile:app:generateVariantBaselineProfile Gradle 任务。

    在已启用 root 权限的实体设备、模拟器或 Gradle 管理的设备上,将生成器作为插桩测试运行。如果使用的是 Gradle 管理的设备,请将 aosp 设置为 systemImageSource,因为需要对基准配置文件生成器的 root 访问权限。

    生成任务结束时,基准配置文件将复制到 app/src/variant/generated/baselineProfiles

不使用模板创建新的基准配置文件

虽然建议使用 Android Studio 基准配置文件模块模板(首选)或 Macrobenchmark 模板来创建基准配置文件,但您也可以仅使用基准配置文件 Gradle 插件。如需详细了解基准配置文件 Gradle 插件,请参阅配置基准配置文件的生成方式

直接使用基准配置文件 Gradle 插件创建基准配置文件的方法如下:

  1. 创建一个新的 com.android.test 模块,例如 :baseline-profile
  2. :baseline-profile 配置 build.gradle.kts 文件:

    1. 应用 androidx.baselineprofile 插件。
    2. 确保 targetProjectPath 指向 :app 模块。
    3. (可选)添加 Gradle 管理的设备 (GMD)。在下例中,该设备是 pixel6Api31。如果未指定,该插件将使用一部已连接的模拟设备或实体设备。
    4. 应用需要的配置,如下例所示。

    Kotlin

    plugins {
        id("com.android.test")
        id("androidx.baselineprofile")
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath = ":app"
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device = "Pixel 6"
                apiLevel = 31
                systemImageSource = "aosp"
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices += "pixel6Api31"
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices = false
    }
    

    Groovy

    plugins {
        id 'com.android.test'
        id 'androidx.baselineprofile'
    }
    
    android {
        defaultConfig {
            ...
        }
    
        // Point to the app module, the module that you're generating the Baseline Profile for.
        targetProjectPath ':app'
        // Configure a GMD (optional).
        testOptions.managedDevices.devices {
            pixel6Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                device 'Pixel 6'
                apiLevel 31
                systemImageSource 'aosp'
            }
        }
    }
    
    dependencies { ... }
    
    // Baseline Profile Gradle plugin configuration. Everything is optional. This
    // example uses the GMD added earlier and disables connected devices.
    baselineProfile {
        // Specifies the GMDs to run the tests on. The default is none.
        managedDevices ['pixel6Api31']
        // Enables using connected devices to generate profiles. The default is
        // `true`. When using connected devices, they must be rooted or API 33 and
        // higher.
        useConnectedDevices false
    }
    
  3. :baseline-profile 测试模块中创建基准配置文件测试。下例展示的测试会启动应用并等待应用进入空闲状态。

    Kotlin

    class BaselineProfileGenerator {
    
        @get:Rule
        val baselineRule = BaselineProfileRule()
    
        @Test
        fun startupBaselineProfile() {
            baselineRule.collect("com.myapp") {
                startActivityAndWait()
            }
        }
    }
    

    Java

    public class BaselineProfileGenerator {
    
        @Rule
        Public BaselineProfileRule baselineRule = new BaselineProfileRule();
    
        @Test
        Public void startupBaselineProfile() {
            baselineRule.collect(
                "com.myapp",
                (scope -> {
                    scope.startActivityAndWait();
                    Return Unit.INSTANCE;
                })
            )
        }
    }
    
  4. 更新应用模块中的 build.gradle.kts 文件,例如 :app

    1. 应用插件 androidx.baselineprofile
    2. baselineProfile 依赖项添加到 :baseline-profile 模块。

    Kotlin

    plugins {
        id("com.android.application")
        id("androidx.baselineprofile")
    }
    
    android {
        // There are no changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile(project(":baseline-profile"))
    }
    

    Groovy

    plugins {
        id 'com.android.application'
        id 'androidx.baselineprofile'
    }
    
    android {
        // No changes to the `android` block.
        ...
    }
    
    dependencies {
        ...
        // Add a `baselineProfile` dependency on the `:baseline-profile` module.
        baselineProfile ':baseline-profile"'
    }
    
  5. 运行 :app:generateBaselineProfile:app:generateVariantBaselineProfile Gradle 任务,生成配置文件。

  6. 生成任务结束时,基准配置文件将复制到 app/src/variant/generated/baselineProfiles

使用 AGP 7.3-7.4 创建新的基准配置文件

虽然可以使用 AGP 7.3-7.4 生成基准配置文件,但强烈建议至少升级到 AGP 8.1,这样便能使用基准配置文件 Gradle 插件及其最新功能。

如果需要使用 AGP 7.3-7.4 创建基准配置文件,相应步骤与 AGP 8.1 的步骤相同,但以下情况除外:

手动应用生成的规则

基准配置文件生成器会在设备上创建一个人类可读格式 (HRF) 的文本文件,并将其复制到主机中。若要将生成的配置文件应用于您的代码,请按照以下步骤操作:

  1. 在生成配置文件时所用模块的 build 文件夹中找到 HRF 文件:[module]/build/outputs/managed_device_android_test_additional_output/[device]

    配置文件遵循 [class name]-[test method name]-baseline-prof.txt 命名模式,如下所示:BaselineProfileGenerator-startup-baseline-prof.txt

  2. 将生成的配置文件复制到 src/main/,然后将该文件重命名为 baseline-prof.txt

  3. 在应用的 build.gradle.kts 文件中为 ProfileInstaller 库添加一个依赖项,以便在云配置文件不可用的情况下启用本地基准配置文件编译。这是在本地旁加载基准配置文件的唯一方式。

    dependencies {
         implementation("androidx.profileinstaller:profileinstaller:1.3.1")
    }
    
  4. 构建应用的正式版,在此期间,所应用的 HRF 规则会被编译成二进制形式,并且会包含在 APK 或 AAB 中。然后,照常分发您的应用。

对基准配置文件进行基准测试

如需对基准配置文件进行基准测试,请通过负责执行 StartupBenchmarks.ktStartupBencharks.java 文件中定义的基准测试的边线操作,创建新的 Android 插桩测试运行配置。如需详细了解基准测试,请参阅创建 Macrobenchmark 类使用 Macrobenchmark 库自动进行衡量

图 3. 通过边线操作运行 Android 测试。

当您在 Android Studio 中运行测试时,build 输出中会包含基准配置文件带来的速度提升的详细信息:

StartupBenchmarks_startupCompilationBaselineProfiles
timeToInitialDisplayMs   min 161.8,   median 178.9,   max 194.6
StartupBenchmarks_startupCompilationNone
timeToInitialDisplayMs   min 184.7,   median 196.9,   max 202.9

捕获所有必需的代码路径

衡量应用启动时间的两个关键指标如下:

初步显示所用时间 (TTID)
显示应用界面的第一帧所需的时间。
完全显示所用时间 (TTFD)
TTID 加上显示第一帧后显示异步加载的内容所用的时间。

系统会在调用 ComponentActivityreportFullyDrawn() 方法后报告 TTFD。如果从未调用 reportFullyDrawn(),则改为报告 TTID。如果系统调用 reportFullyDrawn(),可能需要延迟到异步加载完成之后再报告相应时间。例如,如果界面包含一个动态列表(如 RecyclerView)或延迟列表,那么可能就要在首次绘制列表之后、因此也就是在界面被标记为完全绘制之后,才通过后台任务来填充该列表。在这种情况下,基准配置文件中将不包含在界面达到完全绘制状态后运行的代码。

如需将列表填充也纳入基准配置文件中,请使用 getFullyDrawnReporter() 获取 FullyDrawnReporter,并在应用代码中为其添加报告程序。一旦后台任务完成列表填充,便释放报告程序。在所有报告程序都被释放之后,FullyDrawnReporter 才会调用 reportFullyDrawn() 方法。这样一来,基准配置文件会包含填充列表所需的代码路径。这不会改变面向用户的应用行为,但可让基准配置文件包含所有必要的代码路径。

如果您的应用使用 Jetpack Compose,请使用以下 API 来指示完全绘制状态:

  • ReportDrawn 表示可组合项已准备好立即进行互动。
  • ReportDrawnWhen 接受一个谓词(例如 list.count > 0),以指明可组合项何时准备好进行互动。
  • ReportDrawnAfter 接受一个暂停方法,该方法完成时表示您的可组合项已准备好进行互动。