如何为 Rust 项目配置 GitHub Action cache

发布: 2022-10-29   更新: 2022-12-18   分类: 效率工具   标签: github rust

文章目录

为了加速 CI 的执行,缓存是非常有效的手段。保证缓存的最高利用率,是使用缓存时最需要关注的点。比如在把整个 target 目录缓存后,何时更新这个缓存?最好的方式是在有依赖变更时,对于 Rust 来说就是 Cargo.lock 有变化,对于 Node 来说就是 package.lock 有变化。

下面我们看看如何利用 cache 这个组件来实现上述效果,主要有三个的参数:

下面用缓存 Rust 项目作为示例进行讲解:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
jobs:
  test:
    timeout-minutes: 20
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@master
      - name: Cache Crates
        uses: actions/cache@v3
        with:
          path: |
            ./target
            ~/.cargo            
          key: debug-${{ runner.os }}-${{ hashFiles('rust-toolchain.toml') }}-${{ hashFiles('Cargo.lock') }}
          restore-keys: |
            debug-${{ runner.os }}-${{ hashFiles('rust-toolchain.toml') }}-
            debug-${{ runner.os }}-            
      - run: cargo test

首先看 key 的定义,分为四个部分,分别是:

  1. 固定值, debug 为了与 release 编译区分开
  2. 变量,操作系统
  3. toolchain 文件 Hash
  4. Cargo.lock 文件 Hash

对于一个 cache 来说,当使用 key 命中时,称为 cache hit ,这时在 Actions 结束时,不需要更新 cache。因此设计这个 key 时,需要注意两点:

  1. key 要能够表示缓存变更,上面四个变量即可以确定一个完整有效缓存
  2. 能够表示缓存变更的字段可能有多个,经常变动的需要放在最后面,上面四个变量就遵循了这个顺序

第二点的设计需要与 restore-key 一起来看。当 Actions 执行时,如果 key 没有不一致,这是说明缓存内容有变,可能是 lock 文件变了,也可能是 toolchain,按照 cache 一般设计来说,key 不一致,是没法使用缓存的。

但这时缓存还是可以用的,比如项目中有 10 个依赖,只是对其中一个做了升级,那么其余 9 个的缓存还是有效的,这时缓存的选取就用到 restore-key 了:

restore-key 指定一系列候选的缓存 key,用作没有命中 key 时的候补缓存

由于候补缓存的方式是从上到下,所以 restore-key 的长度一般都是依次递减。对上面的例子来说,缓存选择方式如下:

只要 key 没有命中,在 Actions 执行结束后,就会去更新缓存,便于下次直接命中。可以看到,通过 restore-key 的巧妙设计,可以保证当前最有效的缓存一直是最“热”的。

注意事项

为了安全、成本,GitHub 对缓存做了如下几点的限制:

  • 如果缓存是在 main 分支上产生,那么所有 main 分支衍生的其他分支都可以用到;但是,同时由 main 衍生的分支 B1、B2,他们产生的缓存,是不能共享的
  • 对于 7 天没有访问的缓存,会被自动删掉
  • 缓存空间只有 10G,超过会按照访问时间 LRU 淘汰

扩展阅读

评论

欢迎读者通过邮件与我交流,也可以在 MastodonTwitter 上关注我。