ブログに戻る
CI/CD GitHub Actions Rails

Runtime-Based Splitting で CI 実行時間を33%短縮した話

GitHub Actions における並列テスト実行の最適化手法

5分で読めます

33%

時間短縮

21%

コスト削減

83%

DB Setup 高速化

課題

CI パイプラインの完了に10分以上かかっていました。RSpec テストは7つの並列ノードで実行されていましたが、ノード間で大きな偏りがあり、6分で終わるノードもあれば10分以上かかるノードもありました。

原因は以下の3つでした:

  • 1. Filesize-based splitting - テストがファイルサイズで分割されており、実行時間は考慮されていなかった
  • 2. 冗長な DB setup - 各ノードが7つのDBを作成していたが、実際に使用するのは1つだけだった
  • 3. 過剰なノード数 - ワークロードに対してノード数が多すぎた

Before vs After 比較

Before: 7ノード
Before: 4分以上の偏りがある7ノード

最遅: 10m 12s · 偏差: 4分以上

After: 5ノード
After: 1分程度の偏りに改善された5ノード

最遅: 7m 24s · 偏差: 1分

解決策

1. Runtime-Based Splitting の導入

ファイルサイズではなく、実行時間に基づいてテストを分散させるよう変更しました。parallel_tests(複数CPUコアでテストを並列実行するgem)のランタイムログ機能を活用しています。

仕組み:

  1. 1. 各ノードがテスト実行時間をランタイムログに記録
  2. 2. ログをアーティファクトとしてアップロード
  3. 3. merge ジョブで全ノードのログを結合しキャッシュに保存
  4. 4. 次回実行時にキャッシュから復元し最適な分散を実現
- name: Run tests
  run: |
    RUNTIME_LOG="tmp/parallel_runtime_rspec.log"
    if [ -f "$RUNTIME_LOG" ]; then
      GROUP_BY="runtime"
    else
      GROUP_BY="filesize"
    fi
    bundle exec parallel_test spec -t rspec \
      --group-by "$GROUP_BY" \
      --runtime-log "$RUNTIME_LOG"

2. DB Setup の最適化

各 CI ノードがセットアップ時に7つのDBを作成していることが判明しました。しかし、各ノードは独立した MySQL サービスを持っており、実際に使用するのは1つだけです。このプロジェクトでは Rails のマイグレーションではなく ridgepole(DSLベースのスキーマ管理ツール)を使用しています。

Before (110s)

parallel:create[7] + ridgepole:parallel_prepare

After (19s)

db:create + ridgepole:apply

3. 並列ノード数の削減

テスト分散の改善と DB setup の高速化により、ノード数を7から5に削減しても許容範囲の wall time を維持できることがわかりました。これにより compute cost を21%削減できました。

結果

指標 Before After 改善
Wall Time 10m 12s 6m 50s -33%
DB Setup 110s 19s -83%
ノード間の偏差 4m 02s 1m 07s -72%
Compute/回 ~43分 ~34分 -21%
年間コスト(推定) $850 $672 -$178

補足: テストコードの改善

ワークフローの最適化に加えて、テストコード自体も改善しました。RSpec の .and マッチャーチェーンを使用して it ブロックを統合し、冗長な before ブロックの再実行を削減しました。

RSpec の最適化テクニックについては、 RSpec 公式ドキュメント(aggregate_failures) や こちらの実践ガイド(英語)が参考になります。

まとめ

最適化の前に計測する

時間がどこで消費されているか(DB setup、テスト実行、ノード間の偏り)を把握することで、最も効果的な最適化を選択できます。

Runtime-based splitting は導入の価値あり

キャッシュの仕組みは多少複雑ですが、テスト分散の改善効果は大きいです。

デフォルト設定を疑う

冗長な DB setup は別の環境からコピーされた設定が原因でした。CI 設定が実際の要件に合っているか、常に確認しましょう。

使用ツール