性能优化
本节我们将了解常见、易操作、收益好的一些性能优化策略。
通用优化策略
考虑通用性的策略时,一般从根本性的方法出发。除了外部硬件条件升级外,最根本的策略还属下述三个点:
- 减负:减少不必要的 Configuration、Task;
- 缓存&增量:缓存编译结果,支持增量编译;
- 并发:Project 和 Task 的多任务并行;
三个策略再结合两个阶段分别考量:配置阶段和运行阶段。
配置阶段的优化:
- 考虑可以直接开启的 Gradle 特性,例如
--configuration-cache,这些特性没有默认开启,一方面可能它们还在孵化(未达到稳定版),另外一方面是需要脚本编写时的配合。 - 考虑自己的脚本、插件、第三方插件的升级,例如采用惰性方式创建 Task,修改 Configuration Cache 兼容的编写方式。
运行阶段的优化:
- 考虑可以直接开启的 Gradle 特性,例如
--parallel,同上它有自身的一些限制和不完善,极端情况下会导致编译过程出错。 - 有一些插件其实可以在 Debug 模式下被禁用:测试相关的插件,例如 Jacoco,我们可能只需要 CI 环境下的默认开启,本地可以加入一个开关到 local.propeties 并默认关闭;资源优化处理相关的插件,例如我开源的 ScratchPaper 插件,其作用于 App 图标的修改,添加区分测试版本的一些元信息,可以设定为打对应的提测包时才启用。
- 考虑自己的脚本、插件、第三方插件的升级,例如使用
WorkExecutor支持任务内的子任务并行,AGP 以及 Kotlin Plugin 最近的几个版本也根据该特性修改子任务并行的实现。
上述的内容基本都可以在 Gradle 的文档中找到:
- "Configuration cache"@Gradle
- "Task Configuration Avoidance"@Gradle
- "Developing Parallel Tasks using the Worker API"@Gradle
- "Parallel project execution"@Gradle
想更进一步去探究每个流程的性能瓶颈,可以使用 --scan --profile 等参数或者 gradle-profile 等工具获取构建过程的详细报告
- "Improving the Performance of Gradle Builds"@Gradle:介绍了深入分析的方法、工具,但对于初学者来说可能投入和收益的比例并不可观。
- "Gradle Enterprise Gradle Plugin User Manual"@Gradle
- "DIY Gradle build optimization"Alex Saveau:用一些实际案例介绍如何针对
--scan等工具的结果去做优化。 - "Hello, my Gradle builds are slow!"@Android:一个 AndroidX 团队使用
--scan分析依赖下载耗时的简单案例(虽然是 Gradle Enterprise 商业版的案例,但这篇文章用到的功能都是免费版就有的)。
Android 构建优化策略
这个部分我仅推荐参考 AGP 官方的文档"优化构建速度",更新及时收益良好,但注意其更多倾向于 Debug 包的优化策略。
- 确保工具已是最新版本
- 创建用于开发的 build 变体
- 单变体项目同步
- 避免编译不必要的资源
- 对调试 build 停用 Crashlytics
- 将静态 build 配置值用于调试 build
- 使用静态依赖项版本
- 创建库模块
- 为自定义构建逻辑创建任务
- 将图片转换为 WebP 格式
- 停用 PNG 处理
- 使用增量注解处理器
- 配置 JVM 垃圾回收器
小结
- 升级 Gradle 及相关插件包括 AGP 是最简单、收益最高的优化策略,其次是优化自己编写的脚本、插件。
- 虽然长期坚持更新 Gradle、AGP 需要一定维护成本,但仔细计算会发现不更新的代价更严重。
- 不必追着“优化小技巧”的文章跑,一方面它们过时的很快;另一方面理解了原理可以从更直接有效的角度切入。