使用 R8 配置分析器

R8 配置分析器是一款工具,旨在通过提供有关应用配置质量的详细洞见,帮助您最大限度地发挥 R8 的性能优势。它允许您通过监控关键指标(具体而言,即缩减得分、优化得分和混淆得分)来跟踪和改进 R8 优化,这些指标表示您的代码库中可用于优化的百分比。通过识别广泛或不必要的保留规则(包括第三方库引入的规则),该分析器可帮助您优化配置,确保 R8 可以尽可能有效地优化您的类、字段和方法。

生成报告

使用 AGP 9.3.0 及更高版本时,您可以使用专用的独立 Gradle 任务生成 R8 配置分析器报告,也可以在 R8 build 期间自动生成该报告。

运行独立的 Gradle 任务(建议在本地使用)

在积极迭代保留规则时,请使用独立的 Gradle 任务快速评估更改的影响,而无需完全构建 APK 或 Bundle:

./gradlew :app:analyzeReleaseR8Config

由于此任务会跳过 APK 或 Bundle 生成,因此它提供的反馈周期要短得多。这样,您就可以快速分析保留规则对缩减得分、优化得分和混淆得分的影响,并立即对其进行优化。HTML 报告在 app/build/reports/r8/r8-config-analyzer-release.html 中生成。

在常规 build 期间自动生成

运行完整的 R8 发布 build(例如 assembleRelease)时,报告会自动在 build/outputs/mapping/release/configanalyzer.html 中生成。 如需在常规 build 期间停用输出的自动生成,请设置以下 Gradle 属性:

android.experimental.r8.enableR8ConfigurationAnalyzer=false

对于 AGP 9.2 及更低版本

对于 AGP 9.2 及更低版本,请将 R8 作为类路径依赖项添加到项目的 settings.gradlesettings.gradle.kts 文件中,以将本地 R8 副本更新到最新版本 :

pluginManagement {
    repositories {
        google()
        mavenCentral()
    }
    buildscript {
        dependencies {
            // Update to a more recent R8 version.
            classpath("com.android.tools:r8:9.4.14")
        }
    }
}

这会使用最新版本的 R8(包括最新的配置分析器),并且仅在分析 R8 配置时临时完成。

现在,您可以在运行启用了 R8 的 build 的 Gradle 任务时设置 com.android.tools.r8.dumpkeepradiushtmltodirectory 系统属性。

./gradlew assembleRelease \
    -Dcom.android.tools.r8.dumpkeepradiushtmltodirectory=<output_directory>

例如,使用以下命令在 /tmp/r8analysis 目录中生成 HTML 报告:

# To create the /tmp/r8analysis folder.
mkdir -p /tmp/r8analysis

# To generate the report in the /tmp/r8analysis folder.
./gradlew assembleRelease \
    -Dcom.android.tools.r8.dumpkeepradiushtmltodirectory=/tmp/r8analysis

解读报告

R8 配置分析器可提供有关应用的 R8 配置以及每条保留规则对应用的影响的洞见。这有助于您从 R8 中获得最大优化,从而提高应用性能。使用以下得分了解您的代码库中有多少可供 R8 优化。

报告摘要部分示例
图 1. 报告摘要部分示例。

缩减得分

当 R8 缩减应用时,它会识别并消除未使用的代码和资源,从而减小应用的整体大小,确保最终 build 尽可能精简。缩减得分会跟踪需要缩减的类、字段和方法的百分比。例如,缩减得分为 66% 表示 R8 可以在 66% 的代码库中执行缩减。

优化得分

R8 会执行方法内联和类合并等优化,从而提高应用的启动速度并改进内存。优化得分会跟踪需要 R8 优化的类、字段和方法的百分比。例如,如果优化得分为 66%,则表示 R8 只能在 66% 的代码库中执行优化。

混淆得分

通过将类、字段和方法混淆为较短的名称,R8 可减少应用的元数据占用空间,从而节省内存。混淆得分衡量的是代码库中可用于混淆的代码百分比。

优化保留规则

为了提高得分并解锁更好的 R8 优化,您应该优化保留规则,使其不会不必要地阻止 R8 优化应用。您应该仅保留使用反射访问的类、方法或字段。

为此,请使用 Keep Rule Analysis

保留规则分析示例
图 2. 保留规则分析示例。

如需查看规则的详细分析,请点击该规则以打开详细信息屏幕。

保留规则分析示例
图 3. 保留规则分析示例。

如何优化保留规则

如需优化保留规则并充分发挥 R8 优化对应用的作用,请执行以下操作:

  1. 对于每条保留规则,请在配置分析器中查看 R8 无法优化的类、字段和方法的百分比。使用此信息来识别阻止大量类、字段或方法优化的保留规则。还会列出每条保留规则阻止的优化属性。
  2. 如果您看到某条保留规则阻止了大量类的优化,则应务必检查该保留规则阻止了哪些类、字段和方法的优化,以查看该规则是否保留了未使用反射动态调用的项。
  3. 通过选择正确的保留选项遵循最佳实践,仅针对必要的 类、字段或方法,从而减少保留规则阻止的优化。
  4. 调查并运行涵盖保留规则受影响的类、字段和方法的测试,并优化保留规则。

检查库的优化

集成第三方库时,这些库通常会包含自己的消费者保留规则,以便与 R8 协同工作。由于库作者无法预测您的具体实现,因此他们有时会编写保守的、影响广泛的规则,这些规则阻止的类、字段和方法比必要的要多。 这可能会阻止 R8 优化与库的实际运行时执行无关的应用部分。您可以使用 R8 配置分析器来识别引入对应用优化产生负面影响的规则的库。

使用配置分析器检查所有合并的消费者保留规则的综合效果。通过分析第三方库中每条保留规则的影响,您可以识别并跟踪阻止应用中大量优化的特定第三方库。

如何优化库

如需解决第三方库引入的保留规则,请执行以下操作:

  • 如果某个库包含过于宽泛的规则,我们建议您使用报告中的数据与该库的维护人员联系,以说明其当前规则如何影响应用的优化得分。如果是外部库,请在提交问题之前查找库中现有的 bug。
  • 如有必要,您可以过滤掉特定库中的规则,以测试潜在的改进。您可以将库的规则导入到项目中,排除宽泛的规则,然后重新运行配置分析器,以衡量大小和性能方面的潜在提升。

被取代的规则

在某些情况下,可能会有多个保留规则重叠,其中一条规则可能会阻止比必要更多的优化。如果您的代码库中有两条保留规则。

# Prevents optimization in the entire package
# Remove this to improve optimization
-keep class com.example.package.** { *; }

# Prevents optimization to the class inside the package
-keep class com.example.package.Myclass

第一条保留规则阻止了整个软件包的优化,取代了第二条保留规则,后者针对的是第一条保留规则保留的软件包中的类。当保留规则重叠时,其中一条规则可能会阻止比必要更多的优化。通过优化这些重叠的规则,您可以最大限度地发挥 R8 优化,并消除技术债务。此过程涉及简化配置,确保仅保留必要的代码,同时充分发挥 R8 的优化功能。

报告摘要部分示例
图 4. 报告中被取代的规则示例。

优化被取代的规则

  1. 使用 R8 配置分析器查找取代的保留规则。
  2. 确定代码库中实际依赖于反射的确切类、字段或方法,这些类、字段或方法需要使用保留规则保留。 了解这一点有助于您优化保留规则。
  3. 使用配置分析器比较针对相同类、字段或方法的每条规则的影响。您可以使用每条保留规则阻止的优化百分比来识别哪些是宽泛的保留规则,哪些是狭窄的保留规则。
    1. 如果狭窄的规则编写得非常精确(仅保留以反射方式访问的确切成员或类),则移除宽泛的保留规则。这样可以安全地为软件包的其余部分解锁 R8 优化。
    2. 如果宽泛的规则针对的是正确的类,请保留宽泛的规则并删除狭窄的规则。狭窄的规则只是多余的杂乱内容。 请务必优化宽泛的规则,使其仅针对您已识别的类、字段或方法。

验证并测试更改:重新运行配置分析器,确保 冲突已解决。然后,编译发布 build 并测试您的 更改,确保代码库按预期运行。

移除不必要的规则

使用配置分析器,您可以系统地审核代码库,以识别并修剪使配置杂乱过时的保留规则。R8 配置分析器专门突出显示了不必要规则的两个主要来源:

  • 未使用的规则:与 当前 build 中的零个类、方法或字段匹配的规则。它们通常在代码重构、依赖项移除后或从不再相关的复制粘贴配置中保留下来,从而增加了不必要的配置复杂性。
  • 相同的规则:相同的保留规则是指针对相同的 类、字段和方法的规则,或在相同 或不同的保留规则文件中重复声明的保留规则。

这两种类型的规则都会使配置变得杂乱,从而使维护和调试更加困难。通过识别这些规则,您可以清理配置。