1. Gradle 构建概述
说到 Gradle,很多人第一反应就是“慢”。但在我看来,慢不是 Gradle 的原罪,是我们没搞懂它到底在干什么。我做了几年构建优化,说白了,Gradle 构建就像一条流水线,你如果不清楚每条传送带在运什么、在哪堵住了,那优化就是瞎忙活。
所以呢,咱们先不急着讲瀑布图。我用一张图带你看清楚 Gradle 构建的完整流程,帮你建立一个全局认知。这样后续讲诊断瓶颈时,你才知道我们到底在看什么。
1.1 Gradle 是什么?为什么要关注它的构建过程?
Gradle 是一个基于 JVM 的自动化构建工具。它用 Groovy 或 Kotlin DSL 写脚本,底层依赖了 Ant 和 Maven 的思路,但搞了一套更灵活的 Task 依赖机制。我最早接触 Gradle 是被 Android 项目带进去的,那时还用的是 Maven。换到 Gradle 后,第一感觉是——好家伙,配置文件简单多了,但构建时间怎么还变长了?
后来我明白了。Gradle 的强大在于它支持增量构建和构建缓存,但这些特性发挥好,前提是你得理解它的工作方式。说白了,Gradle 构建分为三大阶段:初始化阶段、配置阶段、执行阶段。每个阶段的耗时,都会在瀑布图上留下痕迹。
核心观点: 构建优化不是拍脑袋,而是基于数据的决策。瀑布图就是你的“X光片”,它能把每个阶段的时间消耗可视化出来。
1.2 构建流程的三大阶段
我习惯把 Gradle 构建比喻成做饭。初始化是洗菜备料,配置是定菜谱,执行是开火炒菜。任何一个环节卡壳,这顿饭就慢。
| 阶段 | 主要工作 | 常见瓶颈 |
|---|---|---|
| 初始化阶段 | 解析 settings.gradle,确定参与构建的项目 | 多项目扫描、插件加载 |
| 配置阶段 | 解析所有 build.gradle,生成 Task 依赖图 | 大量动态配置、依赖解析耗时 |
| 执行阶段 | 按依赖图顺序执行 Task,包括编译、打包等 | 编译耗时、网络下载、IO 瓶颈 |
你想想看,如果你在配置阶段写了太多闭包、每次都去远程仓库检查依赖版本,那瀑布图的配置阶段时间就会异常高。我之前在一个大项目里看到配置阶段占了整个构建时间的 60%——简直离谱。
1.3 核心构建要素
除了三个阶段,还有几个要素是诊断瓶颈时必须盯住的:
- Task: Gradle 的最小执行单元。每个编译、打包动作都是一个 Task。
- Dependency: 构建依赖,包括项目依赖和外部依赖。依赖解析的耗时直接影响配置阶段。
- Plugin: 插件负责引入 Task 和扩展构建逻辑。插件越多,配置阶段越长。
- Build Cache: 构建缓存的命中率直接影响执行阶段的时间。
个人小技巧: 我建议你在做优化前,先跑一次 --scan 参数(Gradle 6.0+ 已内置)。它会生成一个详细的构建扫描报告,里面就已经有瀑布图形式的阶段耗时分布了。不需要等到后面用第三方工具。
1.4 关键构建阶段的时间占比分析
那么,一个健康的 Gradle 构建,各阶段的时间应该是怎样?我记得有一个业内参考数据:
- 配置阶段: 通常占 10%-20%。(如果超过 30%,恭喜你,中奖了。)
- 依赖解析: 占 5%-15%,取决于仓库数量和网络条件。
- 编译(执行阶段的核心): 占 50%-70%,这里是最值得优化的地方。
- 打包/签名等: 占 5%-10%。
为什么我会特别关注配置阶段?因为很多时候,配置阶段消耗的 CPU 和 IO 并不比编译少,而且最容易被人忽略。我在一个客户项目中遇到过配置阶段占了 40% 的情况,排查后发现是每个子项目都在配置阶段动态下载一个很大的依赖版本列表。改成分发固定版本后,配置阶段直接降到 15%。
1.5 网络与 IO:容易忽略的“隐形杀手”
你想想看,Gradle 构建看似在本地跑,但实际上它从始至终都在和网络打交道。从依赖下载、到插件更新、到远程缓存上传/下载,每一个网络请求都可能成为你的构建瓶颈。
尤其是在企业级项目中,依赖仓库可能在公司内网,也可能在公有云。我曾经见过一个案例,构建时间 90 秒,其中 40 秒都在等一个慢速 Maven 仓库返回依赖元数据——这就是典型的网络瓶颈。瀑布图在依赖解析阶段会有一个很长的阻塞条,一眼就能看出来。
注意: 如果你发现瀑布图上依赖解析阶段的请求大量出现了明显的等待时间(比如 300ms 以上甚至几秒),那基本可以断定网络是元凶。我们的课程后续会专门讲如何用瀑布图定位这些请求。
1.6 总结一下
这一章我带你理清了 Gradle 构建的骨架:三个阶段、几个关键要素、以及网络 IO 对构建的影响。其实你做优化,无非就是在这几个点上做文章。
为什么要先讲这些?因为后面所有的瀑布图分析技巧,都是围绕这些阶段展开的。没有一个全局认知,你看到的瀑布图就是一堆花花绿绿的条形,根本不知道哪一条是病根。我刚开始学的时候也走过这个弯路,对着瀑布图瞎猜半天,后来发现是依赖缓存没配置。