「Assignment rules」でCIのコスト削減!Nx Agentsの新機能を使ってみました

ファインディ株式会社 でフロントエンドのリードをしております新福(@puku0x)です。

弊社では、フロントエンド系のリポジトリの多くに Nx を採用しています。

Nxは、Nx Cloudと連携することでCIの高速化やコストパフォーマンスの改善が期待できます。

直近のアップデートにより、Nx Agents(Nx Cloudが提供するサービスの1つ)の新機能「Assignment rules」が正式リリースされました。

nx.dev

これまで解決が難しかったタスク割り当ての最適化が、いよいよ解決できそうです👏

今回はAssignment rulesの解説と、実際に使った場合の効果をご紹介しようと思います。

Nx Agentsとは?

Nxには、Distribute Task Execution(DTE)というCI高速化の機能があります。

nx.dev

DTEでは、ビルドやテストといったタスクを複数のCIマシンで分散実行します。単純なタスク別の並列化と比較して、CIマシンの数を増やした際の高速化の効率が良いという特徴があります。

Nx Agentsの動作イメージ(Nx公式ドキュメントより抜粋)

DTEのマネージドサービスが「Nx Agents」であり、ファインディでは昨年Nx Agentsを導入し、CIの高速化に成功しました。

tech.findy.co.jp

DTEの革命「Assignment rules」

Nx Agentsの課題

Nx Agentsを用いたDTEでは、CIの負荷に応じて利用するマシンの台数やスペックを動的に切り替えられます。

次の設定は、スペックが中程度のマシン3台を最小構成とし、Nxが検知したCIの負荷(=コードの変更に影響のあるプロジェクトの割合)をもとに、高スペックなマシンを混ぜつつ最大8台でCIを動かす例です。

distribute-on:
  00-changeset-s: 3 custom-linux-medium-js
  01-changeset-m: 3 custom-linux-medium-js, 2 custom-linux-large-js
  02-changeset-l: 4 custom-linux-medium-js, 4 custom-linux-large-js
  # changesetは任意の数を定義できます
  # マシンスペックは https://nx.dev/pricing#resource-classes 参照

この機能はCIの高速化に役立つ一方、課題もありました。

  • コア数の多いCPUを活用できない
    (Nxの --parallel オプションはCI全体に適用されてしまう)
  • 負荷の高いタスクがスペックの低いマシンで実行されるのを防げない

後者は特にメモリ不足によるエラーを発生させやすく、CIの再実行にかかる時間やコスト・開発者体験の低下が問題となっていました。

Assignment rulesの登場

そんな時に現れたのが「Assignment rules」です。

nx.dev

この機能により、メモリ不足の最大の要因であった「負荷の高いタスク」をスペックの高いマシンに割り当てるといったことが可能になりました。

また、タスク単位で parallelism を設定することで、マシン内の最大タスク並列実行数を調整でき、コア数の多いCPUを有効活用できます。

設定の例をお見せします。

assignment-rules:
  - projects:
      - app1    # アプリケーション用のタスクを想定
    targets:
      - build*  # build や build-storybook が該当
      - typecheck
    run-on:
      - agent: custom-linux-medium-js
        parallelism: 1  # メモリが足りなくなるため並列実行させない
      - agent: custom-linux-large-js
        parallelism: 3  # 高スペックなマシンの場合は並列実行させる

  - targets:
      - build
      - test
      - typecheck
    run-on:
      - agent: custom-linux-medium-js
        parallelism: 2
      - agent: custom-linux-large-js
        parallelism: 4

  - targets:
      - cspell
      - lint
      - stylelint
    run-on:
      - agent: custom-linux-medium-js
        parallelism: 6
      - agent: custom-linux-large-js
        parallelism: 8

Assignment rulesの効果

比較対象として、4コアマシン×8台の場合を設定します。
参考: Nx Agentsを導入してフロントエンドのCIを約40%高速化しました - Findy Tech Blog

Assignment rulesによってCI時間やコストがどれほど変化したかを見てみましょう。

次の表は、キャッシュヒット無しで全てのタスクが実行された場合のCI時間および想定されるCIのコストを表しています。

Before After(Assignment rules有効)
CI時間 10m 31s 10m 54s
コスト $0.968 $0.726

CI時間はそれほど変わらず25%ほど安くなりました。

マシンスペックを抑えた場合のメモリ不足を心配する必要が無くなったのも嬉しいところです。

まとめ

Assignment rulesにより、Nx Agentsを用いたCIはさらに最適化されます。

個人的に parallelism での並列数設定は待望の機能でした。
(あとは各タスクの優先度を設定できたら最高なのですがNrwlの皆さんいかがですか...!?)

CIの高速化・安定化は、チームのパフォーマンスを考える上で重要になります。Nxの機能の活用により、強固な開発の仕組みを構築できるでしょう。

今後もNxに目が離せませんね👍


ファインディでは一緒に会社を盛り上げてくれるメンバーを募集中です。興味を持っていただいた方はこちらのページからご応募お願いします。

herp.careers