Gradle 构建缓存整体认知
1.1 构建缓存的核心原理
Gradle 构建缓存是一项将任务(Task)的输入与输出进行哈希签名后存储复用结果的机制。每次构建时,Gradle 根据当前任务的输入(源文件、依赖版本、配置参数等)计算出一个唯一缓存键(cache key),并在本地或远程缓存中查找该键是否存在。若命中,则直接复用输出,跳过任务执行;若未命中,则正常执行任务并将输出存入缓存,供后续构建使用。
其核心依赖三要素:
- 输入快照(Input Snapshot):对任务的所有输入(文件内容、类路径、属性等)进行哈希。
- 缓存键(Cache Key):由输入快照、任务类名、执行参数等组合生成。
- 输出归档(Output Archive):任务产物(class 文件、JAR、报告等)打包后与缓存键关联存储。
| 特性 | 传统构建 | 开启缓存构建 |
|---|---|---|
| 编译时间(无变更) | 全量编译(~60秒) | 缓存命中(~2秒) |
| 输入哈希计算 | 无 | 每次必须计算(开销极小) |
| 任务执行次数 | 每次构建全部执行 | 仅输入变更时执行 |
| 远程协作 | 不支持 | 可共享缓存(远程缓存) |
通过日志确认缓存行为: 在
gradle.properties 中添加 org.gradle.caching.debug=true,构建时即可看到每个任务的缓存键、命中状态及存储耗时。
1.2 构建生命周期与缓存的交互
Gradle 构建生命周期分为三个阶段:初始化(Initialization)、配置(Configuration)、执行(Execution)。缓存机制出现在执行阶段。具体流程如下:
- Gradle 为每个任务确定执行所需的输入。
- 在执行前,通过缓存键查询本地/远程缓存。
- 若命中 → 跳过任务执行,直接将输出解压到输出目录。
- 若未命中 → 正常执行任务,执行完成后将输出打包并写入缓存。
- 最终汇总构建结果。
下图清晰展示了该流程:
1.3 缓存带来的加速效果
缓存对多模块项目、频繁拉取分支的场景提升尤为显著。以下是典型实践中的加速数据:
- 全量构建(无缓存):5分20秒
- 二次构建(仅有增量文件变更):45秒(增量构建)
- 跨分支切换后首次构建(缓存命中部分任务):1分10秒
- 跨机器共享缓存(远程缓存):完全一致环境最快可达 5 秒完成
开启构建缓存的配置极为简单:在 gradle.properties 或 build.gradle 中启用即可:
# gradle.properties
org.gradle.caching=true
# 可选:指定本地缓存大小
org.gradle.caching.local.cacheSizeMB=2048
注意: 缓存并不适用于所有任务。例如会改变全局状态的任务(如自定义代码生成器依赖当前时间戳)不应被缓存。此类任务需手动标记为
outputs.cacheIf { false } 或使用 @DisableCachingByDefault 注解。
为验证加速效果,可以在构建后通过 --build-cache 参数显式启用,并观察控制台日志中的缓存命中状态:
# 启用缓存执行构建
gradle build --build-cache
# 输出示例(关键行)
> Task :core:compileJava FROM-CACHE
> Task :data:compileJava UP-TO-DATE
> Task :web:compileJava FROM-CACHE
BUILD SUCCESSFUL in 12s
3 actionable tasks: 2 from cache, 1 up-to-date
其中 FROM-CACHE 表示任务输出来自缓存,未实际执行;UP-TO-DATE 表示本地增量构建认为无需执行。缓存与增量构建协同工作,进一步压缩构建耗时。