如何使用 sccache?

解读

在国内 Rust 岗位面试中,**“如何加速编译”**是高频考点。sccache 作为 Mozilla 开源的分布式编译缓存工具,能把 rustc 产物缓存到本地磁盘或 Redis,二次编译时直接命中,CI 时间从十几分钟降到几十秒,是工程化落地的标配。面试官想确认:

  1. 你是否知道 Cargo 原生不支持跨项目共享增量
  2. 能否在 公司内网 GitLab CI + 自建 Redis 场景下,把 sccache 配成“开箱即用、可灰度、可观测”的状态;
  3. 是否理解 缓存 key 的哈希因子(rustc 版本、代码、flags),避免“缓存污染”导致线上事故。

知识点

  • sccache 与 ccache 差异:前者支持 Rust、C/C++、NVCC,后者仅 C 家族。
  • 两种启动方式
    1. 包管理器安装后 export RUSTC_WRAPPER=sccache
    2. 源码编译开启 S3、Redis、阿里云 OSS feature,满足国内云原生场景。
  • 缓存 key 组成:rustc 版本、目标三元组、编译选项、源文件内容哈希,任何 –C opt-level 变动都会失效
  • 分布式安全–SCCACHE_REDIS_KEY 做命名空间隔离,防止测试环境把生产缓存冲掉。
  • 观测指标sccache –show-stats“cache hits” 与 “cache misses” 直接反映 ROI;Prometheus exporter 可对接夜莺监控。
  • 常见坑
    – 路径中含中文空格导致命中率为 0;
    – 忘记把 target 目录加入 .gitignore,CI 缓存 tar 包爆炸;
    – Windows 上未关杀毒实时扫描,mmap 失败回退到慢速文件 IO

答案

  1. 安装:
    Ubuntu 源版本滞后,推荐用官方预编译静态 musl 包
    wget https://github.com/mozilla/sccache/releases/download/v0.7.4/sccache-v0.7.4-x86_64-unknown-linux-musl.tar.gz
    解压后把单文件放到 /usr/local/binchmod +x

  2. 配置 Redis 后端(公司内网已搭 6.2 集群):

    export SCCACHE_REDIS=redis://:yourPassword@10.0.0.55:6379/1
    export SCCACHE_REDIS_KEY_PREFIX=rust-ci
    export SCCACHE_CACHE_SIZE=20G
    

    20G 可缓存 500 万行 Rust 项目两周迭代量,经验值。

  3. 让 Cargo 调用:

    export RUSTC_WRAPPER=sccache
    export CARGO_INCREMENTAL=0      # 强制关增量,避免与 sccache 冲突
    cargo build –release
    

    首次编译 8 min,第二次 45 s,命中率 96%

  4. CI 集成(GitLab Runner):
    .gitlab-ci.yml 里把 SCCACHE_DIR: $CI_PROJECT_DIR/sccache 缓存到 key: rustc-$RUSTC_VERSION
    Job 结束执行 sccache –stop-server 把日志刷到 stdout,方便排查“非确定性编译”导致的 miss

  5. 灰度与回滚:
    若发现缓存污染,立即改 SCCACHE_REDIS_KEY_PREFIX 版本号,老 key 设 TTL 为 1 h,实现零停机回滚

拓展思考

  • 与 bazel-remote-cache 对比:Bazel 缓存粒度是“action”,Rust 规则尚不成熟;sccache 无需改造构建系统,在 Cargo 体系下 ROI 更高。
  • Rust 1.78 的 –share-generics 与 sccache 叠加:目前仍互斥,等待 rustc 稳定化“模块化代码生成”后,可把泛型实例也缓存,命中率再提 10%。
  • 安全合规:国内金融项目要求“源代码不出内网”,可编译 sccache 时关闭所有 upstream 特性,仅留本地磁盘后端,并用 国密 SM4 全盘加密 防止落地泄露。