GitLab CIのキャッシュ圧縮展開をFF_USE_FASTZIPで爆速にする

毎度、ググっても出てこない小ネタを取り扱っております。
本記事は個人的な見解であり、筆者の所属するいかなる団体にも関係ございません。

# 0. はじめに

GitLabのパイプラインは、使い始めるといろいろやり始めたくなるので、ジョブが増えてパイプライン自体の実行が重くなる事が往々にしてあります。CI/CDパイプラインは少しでも早く終わる方が良いのでGitLabのマニュアルにもジョブ実行をスピードアップする方法のページがあります。

https://docs.gitlab.com/runner/configuration/speed_up_job_execution.html#use-a-distributed-cache

上記のページで紹介されているのがアプリケーションをビルドするときなどに使われる各種ライブラリーを毎回ダウンロードせずに` cache`でキャッシュしてスピードする方法です。しかし、さらにキャッシュの圧縮と展開に時間がかかる場合もあり、それをFastzipを使ってスピードアップする`FF_USE_FASTZIP`のフィーチャーフラグと`CACHE_COMPRESSION_LEVEL`でチューニングするお話です。

https://docs.gitlab.com/runner/configuration/feature-flags.html

https://docs.gitlab.com/ee/ci/runners/configure_runners.html#artifact-and-cache-settings

Fastzipは、複数のコアでZipファイルの圧縮と展開を行うので、GitLab Runner標準のZipよりも早くなります。
Runnerが複数コアのマシンで動いており、Diskのパフォーマンスにも余裕がある場合には、`FF_USE_FASTZIP`を使うことによりCI/CDパイプラインのジョブ実行時間が短縮される可能性があります。

# 1. 設定方法

.gitlab-ci.ymlに以下の内容を記載します。

```yaml:.gitlab-ci.yml
variables:
  # Fastzip is a performant archiver for cache/artifact archiving and extraction
  FF_USE_FASTZIP: "true"

  # *_COMPRESSION_LEVE can also be set to fastest, fast, slow and slowest. 
  # If just enabling fastzip is not enough try setting this to fastest or fast.
  ARTIFACT_COMPRESSION_LEVEL: fast
  CACHE_COMPRESSION_LEVEL: fast

  TRANSFER_METER_FREQUENCY: 3s # will display transfer progress every 5 seconds for artifacts and remote caches.
```

設定の肝は、`FF_USE_FASTZIP: "true"`と`CACHE_COMPRESSION_LEVEL` です。

設定|設定値|デフォルト値|詳細
---|----|----|---
FF_USE_FASTZIP| "true" | "false"| FastZipを利用する
ARTIFACT_COMPRESSION_LEVEL|fastest(無圧縮), fast, slow, slowest| slow | Artifactsの圧縮レベル
CACHE_COMPRESSION_LEVEL|fastest(無圧縮), fast, slow, slowest| slow | Cacheの圧縮レベル

FF_USE_FASTZIPのデフォルトは、falseです。

# 2. ベンチマーク
## 2-1. 利用した.gitlab-ci.yml

FF_USE_FASTZIPを使った場合と使わない場合でどれぐらい圧縮スピードが違うのか確認してみました。
テストに使った`.gitlab-ci.yml`は以下の通りです。
FF_USE_FASTZIPを使わない場合は、`variables:`の項目を削除しました。

1KBのファイルを100*100*10の10万ファイル作ってみました。

```yaml:.gitlab-ci.yml
variables:
  FF_GITLAB_REGISTRY_HELPER_IMAGE: "1"
  FF_USE_FASTZIP: true
  ARTIFACT_COMPRESSION_LEVEL: slow # can also be set to fastest, fast, slow and slowest. If just enabling fastzip is not enough try setting this to fastest or fast.
  CACHE_COMPRESSION_LEVEL: slow # same as above, but for caches
  TRANSFER_METER_FREQUENCY: 3s # will display transfer progress every 5 seconds for artifacts and remote caches.

default :
    image: ubuntu

stages:
   - create-cache
   - restore-cache

create-sample-cache:
  stage: create-cache
  script: 
      - rm -rf cache-test
      - mkdir -p cache-test
      - cd cache-test
      - for i in {1..10}; do 
      -   mkdir -p $i
      -   cd $i
      -   for j in {1..100}; do
      -     mkdir -p $j
      -     cd $j
      -     for k in {1..100}; do dd if=/dev/urandom of=testfile${k} bs=1k count=1 > /dev/null 2>&1 ; done
      -     cd ..
      -   done
      -   cd ..
      - done
      - cd ..
  cache:
    paths:
      - cache-test/*
  tags:
    - k3s

echo-sampel-cache:
  stage: restore-cache
  script:
      - date
  cache:
    paths:
      - cache-test/*
  tags:
    - k3s
```

## 2-2. 圧縮スピードの変化

### 2-2-1. FF_USE_FASTZIPを使わなかった場合

4回ほど実行しましたが、Cache作成までに11～12秒でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/3e1054cf-6ca8-19ed-3127-bab6516e8dcf.png)

### 2-2-2. FF_USE_FASTZIPを使った場合

4回ほど実行しましたが、Cache作成までに3～4秒でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/4aa4977c-6845-20a6-d290-bda9ea700ec5.png)

## 2-3. 展開スピードの変化

### 2-3-1. FF_USE_FASTZIPを使わなかった場合

4回ほど実行しましたが、Cache展開までに4秒でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/e5039df1-523a-79ae-1b85-2f7fe8642246.png)

### 2-3-2. FF_USE_FASTZIPを使った場合

4回ほど実行しましたが、Cache展開までに2秒でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15176/00ad3003-ff0c-5bf2-7ca7-d895ebdd5d88.png)

# 3. まとめ

`FF_USE_FASTZIP`を使うことによって圧縮時には3倍程度、展開時には2倍程度のスピードアップがあることが確認されました(CPU4コア)。
GitLab CI/CDパイプラインでキャッシュを上手く使うことはスピードアップに重要なテクニックの一つです。さらに、`FF_USE_FASTZIP`を使ってさらにスピードアップさせましょう。
また、`CACHE_COMPRESSION_LEVEL`をチューニングすることにより、もっとスピードアップできる可能性があります。