1. Gradle 缓存机制总览:缓存分级、任务输出缓存、构建缓存与本地缓存区别
Gradle 的缓存体系是提升构建速度的核心基础设施。理解其分级结构、查找路径以及各缓存角色之间的差异,是后续优化命中率的理论前提。本章从宏观架构切入,依次剖析缓存层级、两种主要缓存类型(任务输出缓存与构建缓存)以及本地/远程缓存的实际差异。
1.1 缓存分级与查找路径
Gradle 按以下顺序查找缓存,一旦命中即停止搜索:
- 任务输出缓存(Task Output Cache) – 每个任务执行完成后,其输出(产物、文件)按输入哈希存入本地临时区域。同一项目/机器再次构建相同输入时直接跳过任务。
- 本地构建缓存(Local Build Cache) – 跨项目共享的持久化缓存,存储在
~/.gradle/caches/。当任务输出缓存未命中时,查询此层。 - 远程构建缓存(Remote Build Cache) – 通过 HTTP(如 Gradle Enterprise 或自建缓存服务)实现的跨机器共享缓存。仅在本地两级均未命中时回源。
若所有缓存均未命中,Gradle 会执行任务并将输出同时写入任务输出缓存与本地构建缓存(远程缓存需额外推送配置)。
1.2 任务输出缓存 vs. 构建缓存
| 维度 | 任务输出缓存 | 构建缓存 |
|---|---|---|
| 作用域 | 单次构建运行时,临时存储任务输出 | 持久化存储,跨项目、跨构建共享 |
| 存储位置 | 内存或临时目录(build/ 内) |
~/.gradle/caches/ 或远程服务器 |
| 生命周期 | 构建结束后可清理(垃圾回收) | 长期保留,受 TTL 和保留策略控制 |
| 命中条件 | 输入哈希完全匹配 | 输入哈希完全匹配 + 缓存 key 相同 |
| 典型用途 | 同一台机器增量构建 | CI 节点间共享、开发者间共享 |
1.3 本地缓存与远程缓存对比
| 对比项 | 本地缓存 | 远程缓存 |
|---|---|---|
| 存储介质 | 本地磁盘(SSD/HDD) | HTTP 服务器(如 Gradle Enterprise、Nginx) |
| 访问延迟 | 微秒级(本地 I/O) | 毫秒~秒级(网络往返) |
| 容量限制 | 受磁盘空间约束(默认 10GB) | 受服务器容量约束(可弹性扩展) |
| 安全性 | 文件权限控制 | HTTPS + 认证() |
| 配置方式 | 默认自动启用 | 需在 settings.gradle 中指定 buildCache 块 |
1.4 缓存查找流程图
下图展示了从任务输入到缓存的完整查找与回写路径:
关键洞察: 最频繁命中的是任务输出缓存(极低延迟),其次为本地构建缓存。远程缓存仅在跨机器场景下才有意义,不应作为日常增量构建的首选目标。
1.5 默认缓存配置检查命令
通过以下命令可快速查看当前项目及各 Gradle 版本的缓存启用状态:
# 查看 Gradle 版本及缓存目录
gradle --version | grep "Cache"
# 查看构建缓存是否启用(settings.gradle)
grep "buildCache" settings.gradle
# 手动清理本地缓存(谨慎使用)
rm -rf ~/.gradle/caches/
调试提示: 在构建命令后添加
--info 可输出缓存命中/未命中详细日志;使用 --build-cache 强制启用构建缓存,--no-build-cache 禁用。
1.6 常见误区
- 误认为构建缓存 = 任务输出缓存:两者是包含关系,构建缓存是任务输出缓存的上级持久化层。
- 忽视输入噪声:时间戳、路径、构建环境变量等变化会导致缓存 key 改变,即使代码未改也会触发重执行。
- 远程缓存配置后未推送:默认只推送本地缓存,需显式设置
push = true才能将产出推送到远程。
1.7 性能基线指标
缓存命中率每提高 10%,全量构建时间可缩短约 8%~12%(取决于任务体积)。以下为典型环境下的单任务缓存耗时对比:
| 缓存层级 | 单任务命中耗时(微秒) | 单任务未命中执行耗时(秒) |
|---|---|---|
| 任务输出缓存 | 5–20 μs | 0.5–5 s |
| 本地构建缓存 | 100–800 μs | 同上 |
| 远程构建缓存 | 10–100 ms | 同上(网络延迟为主) |
优化目标:将未命中降到最低,优先命中前两级本地缓存。