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