こんにちは、フロントエンドエンジニアのやなぎ( @apple_yagi )です。 GitHub ActionsのBillable timeの削減のために、複数に分けて実行していたJobを、ある程度の粒度でまとめて実行するようにしたので紹介します。
経緯
弊社ではGitHub Enterpriseプランを契約しており、GitHub Actionsを月50,000分使用することができますが、先月(2023/07)使用時間の上限に達したため、一時的にGitHub Actionsが使用できない状況が発生しました。
その月は追加で課金を行なったため、すぐに使えるようになりましたが、そもそも現状の使い方で無駄な箇所がないかを調査することとなりました。
そして調査した結果、Jobを複数に分けて実行することでBillable timeが余分に増えていたことがわかりました。
Billable timeの消費が激しいWorkflow
以下はBillable timeの消費が激しかったWorkflowの1つです。

このWorkflowはフロントエンド用のCIで、install-depsのJobでyarn installを実行し、node_modulesをキャッシュに保存しています。後続のJobではキャッシュからnode_modulesをrestoreし、buildやeslintなどを実行しています。 画像からTotal durationは5分20秒なのに対し、Billable timeは21分となっており、実行時間の約4倍のBillable timeがかかっていることがわかります。
以下は上記のWorkflowで発生したBillable timeの詳細です。

詳細から各Jobに対してBillable timeが個別に発生していることがわかります。そのためWorkflowの合計時間が短時間であっても、使用したマシンの時間分がBillable timeとして計算されていることがわかります。
またinstall-depsのRun timeは31秒なのに対して、Billable timeは1分となっています。これは公式ドキュメントにも記載されていますが、Billable timeが分単位で計算されるため、分単位の切り上げが発生します。
このことからJobをある程度まとめることで余分な分単位の切り上げが減ると考え、直列で実行するように変更しました。
直列で実行した結果
ある程度の粒度にまとめてで実行するようにした結果がこちらです。


Total durationが5分11秒に対して、Billable timeが14分になっており、変更前と比べてTotal durationはほぼ変わらず、Billable timeだけが7分短縮されていることがわかります。また、Run timeも変更前は15分だったのに対して、変更後は11分43秒と約3分ほど短縮されていることがわかります。
Billable timeが短縮されたのはおおよそ想定通りではありましたが、Total durationやRun timeが維持・低下したのは少々想定外だったので調べてみると、Jobを複数に分けることで各Jobにオーバーヘッドが発生していることがわかりました。
ここでいうオーバーヘッドとはnode_modulesをキャッシュからrestoreするステップです。 例として、typecheckのJobを見てみると、Setupというステップで約30秒ほどかかっていることがわかります。

Setupではnode_modulesをキャッシュからrestoreする作業を行なっており、これはJobを分割したことによるオーバーヘッドとなっています。
別の例として、eslintのJobを見てみると、こちらも同様にSetupで約30秒ほどかかっています。

また、typecheckのJobで行っているTypeCheckのステップは14秒、eslintのJobで行っているESLintは23秒と、Setupよりも時間が短いことがわかります。
このことを簡単にまとめると、Setupのようなオーバーヘッドとなるステップよりも短時間で終わるステップを複数Jobに分けると返ってTotal durationとBillable timeが長くなることが言えます。
例として、install-depsとeslint、typecheckのJobを1つにまとめたWorkflowと分割して実行したWorkflowを見比べるとそのことが顕著に現れます。


まとめ
Workflowを複数のJobに細かく分割するとBillable timeで分単位の切り上げが発生し、余分なコストがかかってしまうことや、パッケージのインストールなどが必要なWorkflowを分割すると各Jobに大きなオーバーヘッドが発生することがわかりました。 今後、Workflowを分割するときにはクリティカルパスを計算し、Total durationの短縮に有効なのかどうかを考えてから行いたいと思います。
PR TIMESではフロントエンドはもちろんのこと様々な改善活動が行われているので、もしご興味ある方は、ぜひカジュアル面談でお話しできると嬉しいです。