2. 编译耗时分析工具

编译提速的前提是准确测量耗时分布。Gradle 提供了三个互补的耗时分析工具:控制台实时输出、--profile 离线报告以及Build Scan 云端分析。它们分别适用于不同场景:快速定位单次构建瓶颈、持续跟踪历史趋势、团队共享分析结果。本章将逐一解析它们的原理、使用方法和解读技巧。

2.1 Gradle Console 实时输出解读

Gradle 默认控制台会输出每个 Task 的执行耗时。使用 --info 或 --debug 级别时,信息更详细;推荐在 CI 环境中使用 --console=plain 避免转义字符干扰。

关键输出行示例

> Task :app:compileKotlin 2.345s
> Task :data:compileKotlin 1.123s
> Task :app:lint 4.567s
BUILD SUCCESSFUL in 45.678s
39 actionable tasks: 39 executed
  • Task 耗时:每行末尾的时间是任务的 Wall Clock Time(包含 I/O 等待)。
  • BUILD SUCCESSFUL 总耗时:表示整个构建过程从开始到结束的墙钟时间。
  • executed / up-to-date:揭示增量编译效果。
技巧:关注耗时超过 2 秒的任务,它们通常是优化重点。若某个 Task 标记为 UP-TO-DATE 但依然耗时,说明输入文件探测或缓存检查有开销。

2.2 --profile 离线报告

--profile 参数会在构建结束后生成一份 HTML 报告,位于 build/reports/profile/ 目录下。该报告以时间线和表格形式展示 Task、配置、依赖解析等阶段的耗时。

生成命令

./gradlew clean assembleDebug --profile

报告结构

报告章节 内容说明 典型优化点
Summary 总耗时、Task 数量、缓存命中数 缓存命中低 → 检查输入文件或禁用缓存
Timeline 任务执行时间线(甘特图) 串行 Task 过长 → 并行化或任务合并
Task Execution 每个 Task 的耗时、CPU 时间、GC 时间 高 CPU 时间 → 代码优化;高 GC → JVM 参数调整
Configuration 构建脚本初始化耗时 超过 2 秒 → 减少 plugin apply 或使用生命周期钩子
Dependency Resolution 依赖解析耗时、仓库请求次数 请求过多 → 使用 --offline 或本地缓存
注意事项:--profile 报告仅记录 进程内 耗时,不包含 Gradle daemon 启动时间。若需分析 daemon 启动,请使用 --no-daemon 后收集日志。

2.3 Build Scan 云端分析

Build Scan 是 Gradle Enterprise 提供的付费功能,但开源项目可通过 --scan 免费生成临时链接(有效期 30 天)。它比 --profile 更强大:支持历史对比、性能警告、Task 依赖可视化、缓存命中分析等。

生成命令

./gradlew clean build --scan

构建完成后控制台会输出一个唯一 URL,例如:https://gradle.com/s/abc123。点击即可访问。

关键功能

  • Performance 标签页:自动标记低效 Task、过度序列化、高 GC 停顿。
  • Timeline 标签页:支持放大/缩小,对比两次构建的耗时差异。
  • 缓存分析:显示哪些 Task 从远端缓存命中,哪些因为输入变化而重新执行。
  • Warning 列表:Deprecated Gradle features、Configuration cache misses 等。
适用场景:团队协作时,将 Build Scan 链接分享到 PR 或 CI 日志中,可快速定位构建变慢的原因。建议每次 CI 构建都启用 --scan 并归档链接。

2.4 三工具对比与选型

特性 Gradle Console --profile Build Scan
环境要求 无 无(本地文件) 需网络(上传至服务器)
粒度 Task 级 Task + 配置 + 依赖解析 Task + 配置 + 依赖 + 缓存 + 警告
历史对比 不支持 手动对比文件 自动对比(需 Enterprise 订阅)
推荐场景 日常快速排查 本地深入分析 团队协作与 CI 集成

2.5 各工具的数据流与关系

下图展示了三种工具在 Gradle 构建流程中的位置与数据流向。控制台实时输出来自 Gradle 工作进程;--profile 在构建结束后由 Gradle 主进程生成 HTML;Build Scan 则需额外上传到 Gradle Enterprise 服务器。

编译耗时分析工具数据流 编译耗时分析工具数据流 Gradle 构建进程 解析 settings / build.gradle 控制台实时输出 Task 耗时 & UP-TO-DATE --profile 离线 HTML build/reports/profile Build Scan 云端服务 gradle.com/s/xxxx 使用顺序建议:控制台快速扫描 → --profile 深入分析 → Build Scan 团队共享 / CI 集成 注意:三种工具数据源相同,但 Build Scan 需要网络上传,敏感项目建议离线分析

2.6 常见错误与调试

  • --profile 报告未生成:检查是否有 rootProject.buildDir 访问权限,或是否在子模块执行 --profile(需在根项目执行)。
  • Build Scan 上传失败:确认网络可访问 scan.gradle.com;若使用自托管 Gradle Enterprise,需配置 gradle.properties 中 gradle.enterprise.url。
  • 控制台时间与 --profile 不一致:控制台输出的是墙钟时间(含 JVM GC 停顿),--profile 提供的是线程 CPU 时间,两者可以相差 10%~30%。
调试建议:若某个 Task 在控制台显示 3 秒而在 --profile 中显示 0.5 秒 CPU 时间,说明该 Task 大部分时间花在 I/O 等待上(如网络依赖下载、文件锁竞争),应优先优化 I/O 路径。

2.7 性能优化应用

  1. 基于控制台:找到 Top 3 最具耗时 Task,检查是否能增量执行(开启 @CacheableTask 注解)。
  2. 基于 --profile:关注 Configuration 阶段是否超过 5 秒,若是,使用 configuration-cache 插件或懒加载 allprojects 块。
  3. 基于 Build Scan:利用 Warning 列表修复 Deprecated API,利用缓存分析调整 cacheStrategy 配置。
// 示例:在 gradle.properties 启用配置缓存
org.gradle.unsafe.configuration-cache=true

通过 --profile 对比开启配置缓存前后的 Configuration 阶段耗时,通常能减少 50% 以上。

本章小结:掌握三种耗时分析工具的输出解读,是进行编译提速的第一步。建议在本地开发时日常使用控制台观察;在性能优化阶段使用 --profile 获取详细数据;在团队协作或 CI 中启用 Build Scan 建立性能基线。下一章将基于这些分析结果,讲解 Task 增量编译的具体配置与调优方法。