构建缓存配置与调优

AGP 自 3.6 版本引入构建缓存(Build Cache)机制,通过复用先前构建中生成的中间产物(如字节码、AAR 包、R 文件等),避免相同输入下重复执行耗时任务。缓存分为两级:本地缓存(Local Cache)和远程缓存(Remote Cache)。正确配置缓存策略可大幅缩短构建时间,尤其适用于 CI 环境和多人协作团队。

缓存参数详解

以下为 AGP 构建缓存核心参数及其说明:

参数类型默认值说明
buildCacheDSL 块-顶层配置入口,启用或禁用构建缓存
localCacheDSL 块启用(目录 ~/.gradle/caches/build-cache-1)配置本地缓存目录、最大大小、清理策略
remoteCacheDSL 块未配置配置远程 HTTP 缓存服务地址、凭证、推送策略
cacheStrategy枚举默认策略控制缓存键生成逻辑(如自增构建 ID)、是否启用增量编译

提示:远程缓存需要自建服务或使用 Gradle Enterprise / BuildCache Node。本地缓存默认启用,但未设置大小上限时可能导致磁盘占用异常增长。

实现流程

  1. 启用构建缓存:在 build.gradle 根模块配置 buildCache DSL。
  2. 配置本地缓存:设置目录路径、最大大小(如 5GB)和清理策略(如 retention = 30.days)。
  3. 配置远程缓存(可选):指定 HTTP URL、用户名/密码或 ,并决定是否允许推送缓存。
  4. 调整缓存策略:添加自定义缓存键计算规则(如将 Git 提交哈希纳入键值),避免缓存毒化。
  5. 验证与调试:通过命令行参数 --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 环境变量,不硬编码到源码中。