Gradle构建流水线与阶段划分归纳总结
咱们先别急着调参数、改脚本。你得先搞清楚Gradle到底是怎么干活的。说白了,Gradle的构建过程就像一个流水线,每个阶段都有自己的任务和耗时。如果你连流水线长啥样都不知道,那优化就像闭着眼睛开车——迟早要翻。
我记得刚接触Gradle那会儿,总觉得构建慢就是某个task太恶心了。后来有一次,项目构建从30秒飙到两分半,我抓耳挠腮好几天,最后才发现是配置阶段出了问题——那哥们儿在build.gradle里写了个循环去检查网络资源。从那以后,我养成了一个习惯:先看阶段热力图,再动手优化。
Gradle构建的三个核心阶段
Gradle的构建过程可以拆成三个阶段,每个阶段都有明确的职责。我建议你把这个模型刻在脑子里。
| 阶段名称 | 做什么 | 典型耗时原因 |
|---|---|---|
| 初始化 (Initialization) | 确定哪些项目参与构建,创建Settings对象 | settings.gradle文件过大、动态加载过多配置 |
| 配置 (Configuration) | 解析所有build.gradle,生成Task依赖图 | 脚本逻辑复杂、第三方插件配置慢、动态task生成 |
| 执行 (Execution) | 按依赖顺序执行Task | Task本身耗时长、I/O瓶颈、外部依赖下载 |
阶段之间的“手递手”关系
三个阶段不是独立的,而是串行的。初始化完了才能配置,配置完了才能执行。就像做饭——不能菜还没洗就开始炒。这个“串行”意味着任何一个阶段出问题,后面的阶段都得等着。你想想看,如果配置阶段卡了10秒,执行阶段再快也没用。
我曾经帮一个团队优化构建速度,他们只看Task执行时间,结果发现配置阶段其实占了一半时间。我给他们画了下面这张图,他们瞬间就明白了问题在哪。
每个阶段的“盲区”与瓶颈
很多人以为构建慢就是Task执行慢了。其实不对。我整理了每个阶段最容易出问题的地方,你对照着看下自己的项目有没有踩雷。
Thread.sleep(5000),整个构建就得多等5秒。我曾经在一个遗留项目中看到有人在配置阶段调用curl检查服务器状态,气得我直接想摔键盘。
执行阶段的问题大家都熟悉,但我们往往忽略它的“排队效应”。Gradle的Task虽然是并行的(如果你开启了--parallel),但受限于依赖链——有些Task必须等前面的跑完才能跑。就像去银行办业务,你以为叫了号就快了,结果前面的人办了一个小时。
用--profile查看阶段耗时
Gradle自带一个profile神器。只要在构建命令后面加个--profile,构建结束后会在build/reports/profile/目录下生成一个HTML报告。我个人习惯,每次接新项目第一件事就是跑一次./gradlew clean assembleDebug --profile,然后打开报告看三个颜色的柱状图:
- 蓝色条 —— 初始化阶段耗时
- 红色条 —— 配置阶段耗时
- 绿色条 —— 执行阶段耗时
如果红色条特别长,那你的配置脚本大概率有问题。如果绿色条长,那就去看哪个Task耗时最大。这个报告就是咱们之后制作瀑布图的基础数据来源。
每个阶段的典型优化目标
知道了每个阶段的特点,优化目标就很清晰了。我把它整理成了下面的表格,方便你对照自查:
| 阶段 | 优化目标 | 一句话口诀 |
|---|---|---|
| 初始化 | 减少settings.gradle复杂度,避免动态include | 别在初始化时干重活 |
| 配置 | 把脚本里耗时的操作移到Task里执行 | 配置阶段只建图,不做事 |
| 执行 | 利用缓存、避免重复工作、并行执行无关Task | 能缓存就缓存,能并行就并行 |
tools.jar里的方法去解析某个XML文件,每次配置都要花3秒。我的建议是:如果一定要做,就把它包装成一个Task,放到执行阶段里去跑,这样至少不会影响配置阶段的全局时间。
阶段划分与瀑布图的关系
这份教程的核心是瀑布图。而瀑布图的关键就是:按阶段拆分时间线。我们后面会讲到如何利用Gradle的输出日志和--profile报告,把每个阶段内的耗时拆成一个个小柱子,像瀑布一样从下往上堆叠起来。你可以一眼看出,瓶颈到底卡在初始化、配置还是执行的某个环节上。
现在的你,至少要知道Gradle的构建不是一锅粥——它是分阶段的。下一节我们会深入每个阶段,看看如何具体测量和定位瓶颈。但前提是,你得记住这三个阶段的名字和职责。来,跟我念一遍:初始化、配置、执行。
对,就是这三个。记不住的话,可以理解为:认人(初始化)、分工(配置)、干活(执行)。很形象吧?