1. 分析当前编译瓶颈
多模块项目的编译速度往往随着模块数量和依赖深度的增加而急剧下降。在着手优化之前,必须通过量化手段定位瓶颈所在。本章介绍三种主流分析方法:Gradle Build Scan、--profile 参数 以及 Android Studio 构建输出面板,帮助你准确识别是哪个模块、哪个Task或哪类配置拖慢了整体构建。
1.1 使用 Gradle Build Scan
Build Scan 是 Gradle 提供的云端构建分析工具,能够生成交互式报告,展示每个Task的执行时间、缓存命中率、配置阶段耗时等信息。
启用 Build Scan
在 settings.gradle 或项目的 build.gradle(根项目)中添加以下插件:
// settings.gradle
plugins {
id 'com.gradle.enterprise' version '3.16.2'
}
gradleEnterprise {
server = 'https://your-server.com' // 自托管或使用 Gradle Cloud
allowUntrustedServer = false
}
运行构建时添加 --scan 参数:
./gradlew assembleDebug --scan
构建结束后,终端会输出一个唯一 URL,例如:https://gradle.com/s/abc123。打开即可查看交互式分析页面。
关键指标:在 Build Scan 的“Performance”页面,重点关注 Configuration time、Task execution 和 缓存命中率。如果执行阶段占用超过80%,则瓶颈在Task本身;如果配置阶段超过30%,则需优化脚本逻辑。
1.2 使用 --profile 参数生成本地报告
对于无法访问云端服务的项目,Gradle 提供了内置 --profile 参数,会在 build/reports/profile 目录下生成 HTML 报告。
./gradlew assembleDebug --profile
报告包含三个主要部分:
- Summary:整体耗时、配置 vs. 执行占比
- Task Execution:每个Task的启动时间、持续时间、是否缓存命中
- Memory:GC 暂停次数与耗时
| 列名 | 含义 | 优化线索 |
|---|---|---|
| Task | 执行的Gradle Task名称 | 带 :module: 前缀的路径 |
| Duration | 实际执行耗时(ms) | 超过2秒的Task值得关注 |
| Result | UP-TO-DATE / CACHED / EXECUTED | EXECUTED 表示未命中缓存 |
| Start | 相对项目开始的时间偏移 | 串行度高的Task会堆积 |
1.3 Android Studio 构建输出分析
Android Studio 的 Build Output 面板(View → Tool Windows → Build)会显示每个模块的编译耗时,并且可以通过 Build Analyzer 插件获得更详细的依赖分析。
- 在 Android Studio 中运行一次完整构建。
- 点击 Build 面板下方的 Build Analyzer 标签(如果未显示,请手动打开 View → Tool Windows → Build Analyzer)。
- 查看 Timeline 视图,每个模块用不同颜色条显示:
蓝色 — 配置阶段;
红色 — 编译(javac/kotlinc);
绿色 — 资源处理;
橙色 — 打包/Dex。 - 点击某个颜色块可以看到该模块的Task列表和用时。
常见误区:不要只看总的“Total Time”。例如某个模块耗时仅1秒但被依赖10次,实际累计瓶颈可能是其上游模块的 annotation processing。务必按上游优先分析。
1.4 综合识别瓶颈环节流程图
下图展示了从原始构建到输出瓶颈环节的完整分析流程:
1.5 实际案例分析
假设你有一个包含 8 个模块的项目,运行 --profile 后发现:
:app:compileKotlin耗时 8.2 秒 — 应用模块的 Kotlin 编译:core:network:kaptGenerateStubs耗时 3.5 秒 — 网络模块的注解处理:feature:settings:mergeResources耗时 2.8 秒 — 资源合并
结合 Build Scan 的缓存命中率,发现 kapt 任务从未命中缓存,而其他 Task 缓存命中率达 97%。于是优化方向确定为:升级 KSP 替代 kapt、或配置 kapt.includeCompileClasspath=false。
本章小结:通过 Build Scan、--profile 和 AS Build Output 三种手段,你可以从整体到局部精确定位编译瓶颈。下一阶段将根据识别出的“耗时大户”进行针对性优化。