瀑布图基础 —— 从一片彩色条块中读出构建故事
我第一次打开 AGP 构建分析的瀑布图时,说实话有点懵。
满屏花花绿绿的色块,横轴是时间,纵轴是一堆不认识的任务名。你想想看,一个中型项目光 task 就有上百个,全堆在一张图里,怎么看?
后来我花了两个下午,硬是把每个色块的含义、每个阶段的划分逻辑摸了一遍。从那以后,每次 AGP 版本升级、每次构建变慢,我第一件事就是拉瀑布图。说白了,它就像构建过程的“心电图”,哪儿堵了、哪儿慢了,一眼就能看个大概。
这一章我就把自己读瀑布图的经验拆开来讲。你会发现,这东西没那么玄乎。
瀑布图到底长什么样?
先给个直观印象。下图是我简化后的瀑布图结构,展示了一次构建中几个核心阶段的时间消耗情况。
时间轴 —— 构建的“时钟”
横轴就是时间轴。它的起点是构建开始,终点是构建结束。中间每一个色块从左到右延伸的距离,就是那个任务花掉的时间。
我个人习惯先看总时长。比如上图中,从 0s 到 8s 左右,总耗时约 8 秒。然后我会快速扫一眼哪个色块最长。你看编译阶段那个红色块,占了快一半的时间,这肯定有问题。
时间轴的单位通常是毫秒或秒。AGP 生成的瀑布图会自适应缩放,你鼠标悬停在色块上能看到精确数值。
阶段划分 —— 构建的“工序”
纵轴按阶段把任务分组。每个阶段里可能包含多个子任务,但瀑布图默认会按阶段聚合展示。
常见的阶段包括:
| 阶段名称 | 包含任务 | 典型耗时占比 |
|---|---|---|
| 配置阶段 | 读取 build.gradle、解析依赖、初始化插件 | 1-5% |
| 编译阶段 | Java/Kotlin 编译、APT、注解处理 | 40-60% ⚠️ 通常为瓶颈 |
| 资源处理 | AAPT2、资源合并、shrink | 15-25% |
| 打包阶段 | DEX 编译、APK 打包、混淆 | 15-30% |
| 签名阶段 | APK 签名、zipalign | 1-3% |
我以前在优化一个项目时,发现资源处理阶段特别长。当时以为是图片太多导致的,后来点开瀑布图细看,才发现是 AAPT2 在合并某个大模块的 assets 时卡住了。嗯,这就是阶段划分的价值 —— 帮你快速锁定“哪个工序”出了问题。
色块含义 —— 每一种颜色都在说话
色块是瀑布图的最小信息单元。每一个色块代表一个具体的 Gradle Task。颜色本身没有固定的全局含义,但在同一张图中,同一种颜色通常代表同一类任务或同一个模块。
举个例子:在 AGP 生成的瀑布图里,蓝色可能是配置类任务,红色是编译类任务,绿色是资源类任务。但不同版本的 AGP 配色方案可能不一样,所以别死记颜色,要看图例。
读色块时我一般关注三个信息:
- 宽度 —— 耗时。越宽越可疑。
- 位置 —— 执行顺序。靠左的先执行,靠右的后执行。
- 上下关系 —— 如果两个色块在纵轴上重叠(同一时间段内都有任务),说明它们在并行执行。如果一前一后紧挨着,说明有串行依赖。
1. 先看总时长 —— 心里有个底
2. 找最宽的色块 —— 大概率是瓶颈
3. 看瓶颈色块所属的阶段 —— 锁定了,就是它
4. 观察瓶颈前后是否有串行等待 —— 有时候不是任务本身慢,是它在等别的任务完成
5. 对比两次构建 —— 比如升级 AGP 前后的瀑布图并排看,差距一目了然
如何快速定位瓶颈?三个实用技巧
上面讲的都是基础,下面说点实战的。我在诊断构建速度时,会用到三个技巧:
- 找“最宽的红色块” —— 编译阶段通常占大头,但如果某个模块的编译色块明显比别的宽,那就是它拖了后腿。
- 找“串行长链” —— 如果瀑布图上出现一长串首尾相接的色块,中间没有任何并行,那这条链就是构建的“单行线”。我曾经遇到过一个项目,因为模块依赖没配好,导致 6 个模块串行编译,白白多花了 3 秒。
- 找“空白间隙” —— 色块之间的空白区说明 CPU 在等待 I/O 或等待其他任务完成。空白太多,说明并行度没跑满。
小结
瀑布图说白了就是一张“构建时间地图”。横轴是时间,纵轴是工序,色块是任务。你只要学会看宽窄(耗时)、看颜色(类型)、看位置(顺序),就能快速找到构建的瓶颈点。
下一层楼,我们会拿一份真实的 AGP 升级前后瀑布图做对比分析,看看升级到底带来了哪些变化。但我先把话说在前面——升级不一定全是好事,有时候旧版本里的“隐形优化”在新版本里被拿掉了,瀑布图会诚实地告诉你一切。