构建缓存配置与调优
AGP 自 3.6 版本引入构建缓存(Build Cache)机制,通过复用先前构建中生成的中间产物(如字节码、AAR 包、R 文件等),避免相同输入下重复执行耗时任务。缓存分为两级:本地缓存(Local Cache)和远程缓存(Remote Cache)。正确配置缓存策略可大幅缩短构建时间,尤其适用于 CI 环境和多人协作团队。
缓存参数详解
以下为 AGP 构建缓存核心参数及其说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
buildCache | DSL 块 | - | 顶层配置入口,启用或禁用构建缓存 |
localCache | DSL 块 | 启用(目录 ~/.gradle/caches/build-cache-1) | 配置本地缓存目录、最大大小、清理策略 |
remoteCache | DSL 块 | 未配置 | 配置远程 HTTP 缓存服务地址、凭证、推送策略 |
cacheStrategy | 枚举 | 默认策略 | 控制缓存键生成逻辑(如自增构建 ID)、是否启用增量编译 |
提示:远程缓存需要自建服务或使用 Gradle Enterprise / BuildCache Node。本地缓存默认启用,但未设置大小上限时可能导致磁盘占用异常增长。
实现流程
- 启用构建缓存:在
build.gradle根模块配置buildCacheDSL。 - 配置本地缓存:设置目录路径、最大大小(如
5GB)和清理策略(如retention = 30.days)。 - 配置远程缓存(可选):指定 HTTP URL、用户名/密码或 ,并决定是否允许推送缓存。
- 调整缓存策略:添加自定义缓存键计算规则(如将 Git 提交哈希纳入键值),避免缓存毒化。
- 验证与调试:通过命令行参数
--build-cache启用缓存,并使用--build-cache-debug查看命中情况。
配置示例
以下为 build.gradle 中完整的缓存配置示例(Groovy 语法):
// 根级 build.gradle 或 settings.gradle
buildCache {
localCache {
// 自定义目录(可选)
directory = new File(rootDir, "build-cache")
// 最大缓存占用 5GB
maxSize = "5 GB"
// 保留最近 30 天的缓存
retention = 30.days
// 启用清理任务(默认 true)
removeUnusedEntriesAfterDays = 7
}
remoteCache {
// 远程缓存服务地址(需支持 HTTP PUT/GET)
url = "https://build-cache.mycompany.com/cache/"
// 基本认证(可选)
credentials {
username = "cache-user"
password = System.getenv("CACHE_PASSWORD") ?: ""
}
// 允许向远程推送新缓存(默认 false)
push = true
}
}
// 在 app/build.gradle 中启用构建缓存
android {
...
buildFeatures {
buildConfig = true
}
// 也可以在此显式启用
buildCache {
enabled = true
}
}
注意:远程缓存 push = true 会在每次构建后自动上传产物,需确保服务端支持匿名写入或认证。生产环境建议使用 CI 构建机器推送,开发机仅拉取。
缓存工作流程
调试方法
- 使用
--build-cache-debug参数启动构建,控制台会输出每次任务缓存键及命中/未命中原因。 - 添加 Gradle 日志级别:
--info可查看缓存下载/上传状态。 - 远程缓存调试时,手动访问远程 URL 检查 key 是否存在。示例命令:
curl -X HEAD https://build-cache.mycompany.com/cache/abcdef123456
- 本地缓存目录可通过
gradle --stop后直接浏览~/.gradle/caches/build-cache-1查看缓存的条目。
性能优化结果
| 优化措施 | 典型提速效果 | 适用场景 |
|---|---|---|
| 仅启用本地缓存 | 首次无加速,后续构建减少 30%-40% 差异编译时间 | 单机开发 |
| 本地 + 远程缓存(CI 推送) | CI 环境首次构建提升 50%-70% | 多分支并行 CI |
| 自定义缓存键(纳入 Git 哈希) | 避免缓存毒化,提升命中率 15% | 频繁合并、变基场景 |
实测数据:某大型项目(500+ 模块)配置远程缓存后,CI 构建时间从 25 分钟降至 8 分钟(缓冲命中率 72%)。本地开发清理重构后增量构建时间从 4 分钟降至 1 分钟。
常见错误与修复
| 错误/现象 | 原因 | 修复方法 |
|---|---|---|
| 缓存毒化:构建结果不正确 | 缓存键未包含所有输入(如资源 ID 变化) | 添加自定义缓存键计算,确保将 androidResources 等内容纳入 |
| 远程缓存连接失败 | URL 错误、防火墙拦截、证书过期 | 检查 gradle build-cache-debug 日志;使用 curl 测试服务可达性 |
| 本地缓存无限增长 | 未设置 maxSize 或清理策略 | 添加 maxSize = "5 GB" 和 retention = 30.days |
| 缓存永远未命中 | 多个构建变体共享相同的中间产物,但任务参数不同 | 检查变体配置差异(如 buildTypes 中的 minifyEnabled),统一缓存键 |
关键提示:远程缓存一旦配置 push = true,所有开发机都会向同一地址上传缓存,可能导致大量重复数据。推荐仅 CI 机器开启推送,开发机使用 push = false 只拉取。
缓存策略扩展
AGP 允许通过 buildCache 闭包内的 strategy 函数自定义缓存键。典型策略包括:
- 禁用增量压缩:当输入文件频繁变化时,关闭增量压缩可提升缓存命中率。
- 按分支隔离:将 Git 分支名或提交哈希加入键值,避免不同分支缓存冲突。
- 跨项目共享:设置
localCache.directory指向共享网络目录(需注意并发写入锁问题)。
buildCache {
localCache {
// 将构建目录纳入缓存键
cacheKeyFactory = { task, inputs ->
// 默认工厂会自动处理 inputs,此处可增加自定义参数
inputs.computeCacheKey()
}
}
}
最佳实践:在 settings.gradle 中统一配置缓存,确保所有子模块共享同一缓存配置。将远程缓存 URL 放入 CI 环境变量,不硬编码到源码中。