基准配置文件概览

基准配置文件可以略过所包含代码路径的解译和 即时 (JIT) 编译步骤,从而使代码执行速度在首次 启动时即可提高约 30%。

通过在应用或库中分发基准配置文件,Android 运行时 (ART) 可以通过预先 (AOT) 编译来优化指定的代码路径, 从而针对每位新用户以及每个应用更新提升性能。这种配置文件引导的优化 (PGO) 可让应用优化启动、减少互动卡顿,并提高整体的运行时性能,从而让用户从首次启动开始便获得更好的使用体验。

上述性能增强能够直接提高用户留存率、交易次数和评分等业务指标。如需详细了解 性能对业务指标的影响,请阅读来自 JoshLyftTikTokZomato 的故事。

基准配置文件的优势

基准配置文件可以预先编译关键用户互动中的代码,例如应用启动、切换界面或滚动浏览内容,从而使这些互动自应用首次运行起便更加丝滑。通过提升应用的速度和响应能力,基准配置文件可以提高日活跃用户数和平均回访率。

基准配置文件可以帮助引导应用启动后的优化,通过提供常见的用户互动,从应用首次启动时即开始改进应用运行时环境。引导式 AOT 编译不依赖于用户设备,可以在开发机器(而非移动设备)上为每个版本执行一次。与单纯依赖云配置文件相比,通过使用基准配置文件发布版本,您可以更快速地实现应用优化。

如果不使用基准配置文件,所有应用代码都会在经过解译后在内存中进行 JIT 编译,或在设备处于空闲状态时在后台被写入 odex 文件。安装或更新应用后,一开始运行该应用时,用户的体验会不太理想,直到新的代码路径得到优化。根据测量结果,许多应用在优化后性能会提升约 30%。

启动配置文件

启动配置文件与基准配置文件类似,但它会在编译时使用以优化 DEX 布局,进而加快启动速度,而不是用于设备端优化。如需详细了解启动配置文件与基准 配置文件的区别,请参阅比较基准配置文件和启动配置文件。 如需详细了解 DEX 布局优化,请参阅 DEX 布局优化和启动 配置文件

开始使用

如需开始优化现有应用的性能,请参阅创建基准 配置文件

配置文件生成与发布 build

务必了解在 生成基准配置文件和启动配置文件(例如 baseline-prof.txtstartup-prof.txt)时所需的 build 配置与在构建使用这些配置文件的最终发布版 APK 时所需的 build 配置之间的区别。

生成配置文件(例如 benchmark)时

使用测试捕获基准配置文件时,应用不得经过混淆处理。 为确保生成的配置文件规则与代码的方法签名准确匹配,您必须针对用于生成配置文件的 build 变体关闭混淆处理和优化 (R8)。此变体必须与已启用混淆处理和优化的发布 build 变体不同。您可以通过为配置文件生成 build 变体设置 isMinifyEnabled = false 来实现此目的。如果您未使用基准配置文件 Gradle 插件,还应确保应用了 -dontobfuscate-dontoptimize基准配置文件 Gradle 插件会自动为您处理此配置。

您可以打开生成的文本配置文件(例如 baseline-prof.txt),并检查类名称和方法名称是否未经过混淆处理,从而验证应用在配置文件生成期间是否未经过混淆处理。

构建最终发布版 APK 时

构建发布版应用时,应用应经过混淆处理。您的发布 build 必须具有 isMinifyEnabled = true,才能受益于混淆处理、缩减和优化。R8 会自动重写未经过混淆处理的配置文件中的规则,以与发布版 APK 中经过混淆处理和优化的代码相匹配。build 通过正确转换规则来利用未经过混淆处理的文本文件。

如果您希望 DEX 布局优化(由启动配置文件驱动)正常运行, 则发布版应用必须经过混淆处理,并且使用 R8 并启用所有优化。

高级(非 Gradle)工作流

如果您使用高级非 Gradle 工作流(例如 Bazel、Buck 或自定义 CI 自动化流水线)来生成配置文件,则仍必须遵循相同的原则。捕获配置文件时,应用不得经过混淆处理或优化。但是,在构建发布版应用时,您必须对其进行混淆处理。R8 会处理未经过混淆处理的文本规则文件,并正确转换规则以应用于经过混淆处理的发布版应用。

依赖项链提供稳定发布版本和开发发布版本。如需生成并安装基准配置文件,请使用以下受支持版本或更高版本的 Android Gradle 插件、Macrobenchmark 库和配置文件安装程序。需要使用这些依赖项的时间各不相同,它们会以工具链的形式协同工作,以构建最佳的基准配置文件。

  • Android Gradle 插件:com.android.tools.build:8.0.0
  • Macrobenchmark 库:androidx.benchmark:benchmark-macro-junit4:1.4.1
  • 配置文件安装程序:androidx.profileinstaller:profileinstaller:1.4.1

我们建议您使用最新版本的 AGP 创建和管理基准配置文件。以下是不同版本的 AGP 附带的主要功能:

AGP 版本 功能
9.1 完整源代码集目录支持(库模块): 除了变体感知目录之外,您还可以声明 多个具有任意名称的基准配置文件源文件,例如 src/free/generated/baselineProfiles/baseline-prof1.txt, 为库模块以及应用模块使用。
8.4 使用 Gradle 封装容器命令行工具 或 Android Studio 安装基准配置文件时,本地应用安装的 build 不可调试,因此本地发布 build 的性能 与生产环境更接近。此 更新不会影响基准配置文件的生产环境性能。
8.3
  • 部分源代码集目录支持(库模块): 为库模块声明变体感知基准配置文件,例如 src/free/generated/baselineProfiles/baseline-prof.txt, 。
  • 基准配置文件包含 脱糖类
8.2
  • R8 重写规则: D8 和 R8 可以转换 人类可读的基准和启动配置文件规则,以完整捕获 优化应用性能所需的所有规则。这样,您就可以从缩减前的 build 生成配置文件,并将其应用于缩减后的发布 build。将方法的基准配置文件覆盖率提高约 30%,将应用性能提高约 15%。
  • 启动 配置文件 生成这种类型的基准配置文件,用于 说明 DEX 中的代码布局。将启动性能额外提高约 15%;对于大型应用,升幅可能更高。
8.0 建议的最低版本: 使用基准配置文件 Gradle 插件,通过单个 Gradle 任务生成基准配置文件。
  • 完整源代码集目录支持(应用模块): 声明多个基准配置文件 源文件,并使用变体感知目录,例如 src/free/generated/baselineProfiles/baseline-prof1.txt
7.4 支持的最低版本: 应用可以使用库中的基准配置文件,并在 src/main/baseline-prof.txt 文件中提供自己的基准配置文件。
  • 从 app bundle 构建 APK 时,系统会正确打包基准配置文件(问题 230361284)。
  • 对于具有多个 .dex 文件的应用,系统会针对主要 .dex 文件正确打包基准配置文件。
  • D8 和 R8 支持 从 `isMinifyEnabled` 设置为 `false` 的 build 生成启动配置文件。isMinifyEnabledfalse

变体感知配置文件源设置

通过对应用使用 Android Gradle 插件 (AGP) 8.0 版,对库使用 AGP 8.3 版,您可以将基准配置文件规则放置在专用源代码集目录中,从而摆脱单个固定路径(例如 src/main/baseline-prof.txt)的限制,并启用多个文件。

这有助于实现强大的变体支持,让您可以定义针对特定 build 风味和类型量身定制的不同基准配置文件(例如,使用 src/variant/baselineProfiles/ 等目录),从而确保为每个唯一的应用或库二进制文件准确应用性能优化规则。

配置文件生成示例

以下示例类使用建议的 Macrobenchmark 库,针对应用启动以及几项导航和滚动事件创建基准配置文件:

class BaselineProfileGenerator {
    @get:Rule
    val baselineProfileRule = BaselineProfileRule()

    @Test
    fun appStartupAndUserJourneys() {
        baselineProfileRule.collect(packageName = PACKAGE_NAME) {
            uiAutomator {
                // App startup journey.
                startApp(PACKAGE_NAME)

                // Find and click elements using the new DSL
                onElement { textAsString() == "COMPOSE LAZYLIST" }.click()
                onElement { viewIdResourceName == "myLazyColumn" }.also {
                    it.fling(Direction.DOWN)
                    it.fling(Direction.UP)
                }
                pressBack()
            }
        }
    }
}

如需详细了解如何使用 UI Automator 库自动执行用户 体验历程,请参阅使用 UI Automator 编写自动化测试

查看这些代码时,您可以参阅 GitHub 上的 性能实例,获取完整上下文和更多详细信息。

应添加的内容

在应用中使用基准配置文件时,您可以添加应用启动代码和常见的用户互动,例如切换界面或滚动浏览。您还可以收集完整的流程,例如注册、登录或付款。您认为至关重要的任何用户体验历程都适合利用基准配置文件来提升运行时性能。

如果您正在实验使用不同的方法来提升性能,请考虑为两个实验组都添加基准配置文件。这样,您就可以确保所有用户都能以一致的方式运行编译后的代码,从而更轻松地解读结果。

库可以提供自己的基准配置文件并将其随版本一起发布,以便提升应用性能。例如,请参阅“Jetpack Compose 性能”中的“使用基准配置文件”部分

基准配置文件的工作原理

在开发应用或库时,请考虑定义基准配置文件,涵盖渲染时间或延迟时间非常重要的常见用户互动。 其工作原理如下:

  1. 系统会为您的应用生成人类可读的配置文件规则,并在应用中将其编译为二进制文件格式。您可以在 assets/dexopt/baseline.prof 中找到这些规则。 然后,您可以照常将 Android App Bundle (AAB) 上传到 Google Play。

  2. Google Play 会处理该配置文件,然后将其与 APK 一起直接发布给用户。在应用安装期间,ART 会对配置文件中的方法执行 AOT 编译,以便提升这些方法的执行速度。如果配置文件包含应用启动或帧渲染期间使用的方法,用户使用应用时,启动速度可能会更快,并且卡顿现象可能会更少。

  3. 此流程可与云配置文件汇总功能结合使用,在一段时间后根据应用的实际使用情况对性能进行微调。

图 1. 此图演示了从上传到向最终用户交付的基准配置文件 工作流程,以及该工作流程与云配置文件的关系 。

比较基准配置文件和启动配置文件

您可以使用基准配置文件 Gradle 插件来定义和生成配置文件。 此插件会挂钩到构建流程中,AGP 会将这些人类可读的配置文件规则编译为二进制格式(在 APK 或 AAB 中打包为 baseline.prof),只要小于 1.5 MB,ART 就可以有效地用于设备端编译。

生成的这些配置文件通常命名为 startup-prof.txtbaseline-prof.txt。虽然它们的内容有时看起来可能相似(尤其是当您主要关注启动时),但它们具有不同的用途,并且在不同阶段影响性能:

基准配置文件

基准配置文件包含一组全面的规则,Android 运行时 (ART) 使用这些规则预先编译常用代码路径,从而优化应用性能,而不仅仅是启动性能。

基准配置文件通常是启动配置文件中规则的超集。此文件包含应用启动优化所需的所有规则(通过 baselineProfile Gradle 任务生成),以及其他关键用户体验历程的额外配置文件。例如,滚动和切换不同界面。

无论 includeInStartupProfile 配置字段的值如何,都会生成这些额外的非启动规则。

启动配置文件

启动配置文件包含专门针对应用启动路径优化的规则。在编译期间,D8 会将 Java 字节码转换为 DEX 格式。 然后,R8 会使用此文件来影响 DEX 文件的布局,确保将关键启动代码放置在主 DEX 文件中,以便更快地执行。通常,您应仅针对对应用的初始显示至关重要的测试场景将 includeInStartupProfile 设置为 true。如需了解详情,请参阅 创建启动配置文件

云配置文件

云配置文件与基准配置文件结合使用可以提供另一种形式的 PGO。云配置文件由 Google Play 商店进行汇总,并分发给用户以进行安装时编译。

虽然云配置文件是由用户与应用的实际互动驱动的,但它们在更新后需要几小时到几天的时间才能分发,这就限制了它们的可用性。在配置文件全面分发之前,用户在使用新应用或更新版应用时的应用性能会不太理想。此外,云配置文件仅支持搭载 Android 9(API 级别 28)或更高版本的 Android 设备,也只能针对用户群规模足够大的应用进行理想的扩缩。

各种 Android 版本的编译行为

Android 平台版本使用了不同的应用编译方法,每种方法在性能方面都进行了相应的权衡。基准配置文件提供了一个适用于所有安装的配置文件,对之前的编译方法进行了改进。

Android 版本 编译方法 优化方法
5 至 6(API 级别 21 至 23) 完全 AOT 整个应用会在安装期间进行优化,这会导致用户需要等待较长的时间才能使用应用,RAM 和磁盘空间使用量增加,并且从磁盘加载代码需要更长的时间,进而可能增加冷启动时间。
7 至 8.1(API 级别 24 至 27) 部分 AOT(基准配置文件) androidx.profileinstaller 会在应用首次运行时安装基准配置文件,届时应用模块会定义此依赖项。ART 可以通过以下方法进一步改进这一点:在应用使用期间添加额外的配置文件规则,并在设备空闲时编译这些规则。这可以优化磁盘空间利用率并缩短从磁盘加载代码所需的时间,从而减少用户使用应用需要等待的时间。
9(API 级别 28)及更高版本 部分 AOT(基准配置文件 + 云配置文件) 在应用安装期间,Play 会使用基准配置文件优化 APK 和云配置文件(如果有)。应用安装完毕后,ART 配置文件会上传到 Play 并汇总在一起,然后在其他用户安装或更新应用时,以云配置文件的形式提供给他们。

已知问题

下面列出了可能出现的问题和解决方案,或相关解决方案尚在开发中的问题:

  • 在某些设备(包括一加设备)上,由于权限设置,基准配置文件生成可能会失败。如需解决此问题,请在开发者选项 设置中关闭停用权限监控 选项。

  • 如需成功为库提供基准配置文件,请使用 基准配置文件 Gradle 插件 1.2.3 或 AGP 8.3(最低版本) (问题 313992099)。

  • 如果您使用命令 ./gradlew app:generateBaselineProfile 生成基准配置文件,测试模块中的基准也会运行, 并且结果会被舍弃。如果发生这种情况,您可以通过运行带有 -P android.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile 的命令来仅生成 基准配置文件。 此问题已在 AGP 8.2 中得到修复。

  • 用于为所有 build 类型生成基准配置文件的命令 ./gradlew app:generateBaselineProfile 仅为发布 build 类型生成基准配置文件。此问题已在 AGP 8.1 中得到修复。

  • 非 Google Play 商店应用分发渠道可能不支持在安装时使用基准配置文件。通过这些渠道安装应用的用户无法享受这些好处,直到后台 dexopt 运行(可能一夜过后)。

  • Play 商店内部应用分享不支持基准配置文件 (Baseline Profile);不过,内部测试轨道支持。

  • 在某些设备(例如华为设备)上,电池优化可能会影响配置文件安装。为帮助确保您的配置文件能有效安装,请停用基准设备中的电池优化功能。

其他资源

为你推荐