基准配置文件

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

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

基准配置文件的优势

使用基准配置文件后,所有用户互动(例如应用启动、切换屏幕或滚动内容)都会从首次运行开始变得更加顺畅。提升应用的速度和响应能力有助于提高日活跃用户数和平均回访率。

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

如果不使用基准配置文件,所有应用代码都会在经过解译后在内存中进行 JIT 编译,或在设备处于空闲状态时在后台被编译为 odex 文件。刚刚安装或更新了某个应用的用户无法在首次运行时获得理想的体验,并且这种情况会持续到新路径完成优化。许多应用的实测性能提升幅度都达到了 30% 左右。

开始使用

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

依赖项链提供稳定发布版本和开发发布版本。如需生成并安装基准配置文件,至少需要使用支持的最低版本 Android Gradle 插件、Macrobenchmark 库和配置文件安装程序。这些依赖项会在不同时间需要,并作为工具链协同工作,以实现最佳的基准配置文件。

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

配置文件生成示例

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

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

    @Test
    fun appStartupAndUserJourneys() {
        baselineProfileRule.collectBaselineProfile(packageName = PACKAGE_NAME) {
            // App startup journey
            startActivityAndWait()

            device.findObject(By.text("COMPOSE LAZYLIST")).clickAndWait(Until.newWindow(), 1_000)
            device.findObject(By.res("myLazyColumn")).also {
                it.fling(Direction.DOWN)
                it.fling(Direction.UP)
            }
            device.pressBack()
        }
    }
}

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

应添加的内容

在应用中使用基准配置文件时,您可以添加应用启动代码和常见的用户互动,例如切换屏幕或滚动。您还可以收集完整的流程,例如注册、登录或付款。

库可以提供自己的基准配置文件并将其作为版本的一部分进行发布,以便提升应用性能。例如,您可以查看将基准配置文件与 Compose 搭配使用

基准配置文件的运作方式

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

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

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

  3. 此流程可与云配置文件汇总配合使用,以随着时间的推移根据应用的实际使用情况对性能进行微调。

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

云配置文件

云配置文件可以提供另一种形式的 PGO,它们由 Google Play 商店进行汇总,并与基准配置文件一起分发以进行安装时编译。虽然云配置文件是由用户与应用的实际互动驱动的,但它们在更新后需要几天到几周的时间才能分发,这就限制了它们的可用性。如果单纯依赖云配置文件,那么在该配置文件做好准备并完成分发之前,新用户和更新应用的用户将一直无法体验最佳性能。此外,云配置文件仅支持搭载 Android 9(API 级别 29)或更高版本的 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 并汇总在一起,然后在其他用户安装或更新应用时,以云配置文件的形式提供给他们。

已知问题

目前,使用基准配置文件存在几个已知问题:

  • 从 app bundle 构建 APK 时,未正确封装基准配置文件。如需解决此问题,请采用 com.android.tools.build:gradle:7.3.0 及更高版本(详见问题)。

  • 只针对主 classes.dex 文件正确封装了基准配置文件。这会影响包含多个 .dex 文件的应用。如需解决此问题,请采用 com.android.tools.build:gradle:7.3.0 及更高版本。

  • 不允许在 user(未取得 root 权限)build 中重置 ART 配置文件缓存。为了解决此问题,androidx.benchmark:benchmark-macro-junit4:1.1.0 包含可在基准测试期间重新安装应用的修复程序(详见问题)。

  • 在对应用进行性能分析时,Android Studio 性能分析器不会安装基准配置文件(详见问题)。

  • 非 Gradle 构建系统(Bazel、Buck 等)目前不支持将基准配置文件编译到输出 APK 中。

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

  • 目前,build 编译器只接受 src/main 文件夹中的 1 个 baseline-prof.txt,不反映不同变种或 build 类型的文件。我们正在积极进行改进。

  • 电池优化可能会影响配置文件安装。为了确保您的配置文件能有效安装,请停用基准测试设备上的电池优化功能。

  • 基准测试和生产环境之间在性能改进方面可能有所不同。发生这种情况是因为本地基准测试会在启用或停用基准配置文件 (Baseline Profile) 的情况下测量性能。在正式版应用中,在向基准配置文件添加应用的新部分时,测量结果是增量的,其中部分已通过相关库进行分析。