Bazel ユーザーなら誰でも、ビルドが遅い、または想定よりも遅いという経験があるでしょう。個々のビルドのパフォーマンスを改善することは、次のような大きな影響を与えるターゲットにとって特に重要です。
頻繁に反復処理され、ビルド(再ビルド)されるコア デベロッパー ターゲット。
他のターゲットから広く依存されている共通ライブラリ。
ターゲットのクラス(カスタムルールなど)の代表的なターゲット。 1 つのビルドで問題を診断して修正すると、 大規模な問題の解決に役立つことがあります。
ビルドのパフォーマンスを改善するための重要なステップは、リソースがどこで 消費されているかを把握することです。このページでは、収集できるさまざまな指標について説明します。 ビルドのパフォーマンスを分析することで、 これらの指標を使用してビルドのパフォーマンスの問題を検出して修正する方法を確認できます。
Bazel ビルドから指標を抽出する主な方法は次のとおりです。
Build Event Protocol(BEP)
Bazel は、さまざまなプロトコル バッファ
build_event_stream.proto
をBuild Event Protocol(BEP)を介して出力します。これは、指定したバックエンドで集計できます。ユースケースに応じて、
さまざまな方法で指標を集計できますが、ここでは一般的に考慮すべき概念と proto フィールドについて説明します。
Bazel の query / cquery / aquery コマンド
Bazel には、ターゲットグラフ、構成済みターゲットグラフ、アクショングラフをそれぞれクエリできる 3 つのクエリモード(query、 cquery、aquery)が用意されています。クエリ言語には、さまざまな クエリモードで使用できる 一連の関数が用意されており、必要に応じてクエリをカスタマイズできます。
JSON トレース プロファイル
ビルドのような Bazel の呼び出しごとに、Bazel は JSON 形式でトレース プロファイルを書き込みます。JSON トレース プロファイルは、呼び出し中に Bazel が時間を費やした内容をすばやく把握するのに非常に役立ちます。
実行ログ
実行ログは、マシンと環境の違いや
非決定論的なアクションが原因で
リモート キャッシュ ヒットが欠落している場合のトラブルシューティングと修正に役立ちます。
--experimental_execution_log_spawn_metrics
フラグ(Bazel 5.2 以降で使用可能)を渡すと、ローカルとリモートで実行されたアクションの両方について、詳細な spawn 指標も含まれます。これらの指標を使用すると、たとえば、ローカル マシンとリモート マシンのパフォーマンスを比較したり、
spawn 実行のどの部分が常に想定よりも遅いか(
キューイングなど)を
確認したりできます。
実行グラフログ
JSON トレース プロファイルにはクリティカル パスの情報が含まれていますが、
実行されたアクションの依存関係グラフに関する追加情報が必要になることがあります。
Bazel 6.0 以降では、フラグ
--experimental_execution_graph_logと
--experimental_execution_graph_log_dep_type=allを渡して、
実行されたアクションとその相互依存関係に関するログを書き出すことができます。
この情報を使用して、クリティカル パス上のノードによって追加される遅延を把握できます。遅延とは、実行グラフから特定のノードを削除することで節約できる可能性のある時間です 。
このデータは、ビルドグラフとアクショングラフに変更を加える前に、その影響を予測するのに役立ちます 。
bazel-bench を使用したベンチマーク
Bazel bench は、 Git プロジェクトのベンチマーク ツールで、 次の場合にビルドのパフォーマンスを測定します。
プロジェクトのベンチマーク: 単一の Bazel バージョンで 2 つの Git コミットを比較します。ビルドの回帰( 依存関係の追加によるものが多い)を検出するために使用されます。
Bazel のベンチマーク: 単一の Git コミットで 2 つのバージョンの Bazel を比較します。Bazel 自体の回帰を検出するために使用されます(Bazel を維持またはフォークする場合)。
ベンチマークでは、実時間、CPU 時間、システム時間、Bazel の保持 ヒープサイズがモニタリングされます。
変動要因を減らすため、他のプロセスを実行していない専用の物理マシンで Bazel bench を実行することをおすすめします。