このページでは、キャッシュ ヒット率を確認する方法と、リモート実行のコンテキストでキャッシュミスを調査する方法について説明します。
このページでは、リモート実行を正常に利用するビルドやテストがあり、リモート キャッシュを効果的に利用していることを確認したいことを前提としています。
キャッシュ ヒット率を確認する
Bazel 実行の標準出力で、プロセスを一覧表示する INFO
行を探します。この行は、Bazel アクションにほぼ対応しています。この行には、アクションが実行された場所の詳細が記載されています。remote
ラベルはリモートで実行されたアクションを示し、linux-sandbox
はローカル サンドボックスで実行されたアクションを示します。他の値は他の実行戦略を示します。結果がリモート キャッシュから取得されたアクションは remote cache hit
として表示されます。
次に例を示します。
INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.
この例では、リモート キャッシュヒットが 6 回あり、2 つのアクションはキャッシュヒットがなく、リモートで実行されました。3 つの内部パーツは無視できます。通常、シンボリック リンクの作成などの小さな内部アクションです。この概要にローカル キャッシュ ヒットは含まれません。プロセスが 0 個(または想定よりも少ない数)の場合は、bazel clean
の後にビルド/テストコマンドを実行します。
キャッシュ ヒットのトラブルシューティング
想定したキャッシュ ヒット率が得られない場合は、次の操作を行います。
同じビルド/テストコマンドを再実行するとキャッシュ ヒットが発生することを確認する
キャッシュにデータを入力するビルドまたはテストを実行します。特定のスタックで新しいビルドを初めて実行するときは、リモート キャッシュ ヒットは発生しません。リモート実行の一環として、アクションの結果はキャッシュに保存され、以降の実行で取得されます。
bazel clean
を実行します。このコマンドを実行すると、ローカル キャッシュが消去されます。これにより、ローカル キャッシュ ヒットによって結果がマスクされることなく、リモート キャッシュ ヒットを調査できます。調査しているビルドとテストを(同じマシンで)再度実行します。
INFO
行でキャッシュ ヒット率を確認します。remote cache hit
とinternal
以外のプロセスが表示されない場合は、キャッシュが正しく入力され、アクセスされています。その場合は、次のセクションに進んでください。不一致の原因として考えられるのは、ビルド内の非ハーメチックなものが原因で、2 回の実行でアクションが異なるアクションキーを受け取ることです。これらのアクションを見つけるには、次の操作を行います。
a. 問題のビルドまたはテストを再実行して、実行ログを取得します。
bazel clean
bazel --optional-flags build //your:target --execution_log_compact_file=/tmp/exec1.log
b. 2 つの実行の実行ログを比較します。2 つのログファイルでアクションが同一であることを確認します。不一致は、実行間に発生した変更の手がかりとなります。ビルドを更新して、これらの不一致を解消してください。
キャッシュ保存の問題を解決し、繰り返し実行でキャッシュヒットがすべて生成されるようになった場合は、次のセクションに進みます。
アクション ID が同じなのにキャッシュ ヒットがない場合は、構成の何かが原因でキャッシュ保存が妨げられています。このセクションに進んで、一般的な問題を確認してください。
実行ログ内のすべてのアクションで
cacheable
が true に設定されていることを確認します。特定のアクションの実行ログにcacheable
が表示されない場合は、対応するルールがBUILD
ファイルの定義にno-cache
タグを含んでいる可能性があります。実行ログのmnemonic
フィールドとtarget_label
フィールドを確認して、アクションの発生元を特定します。アクションが同じで
cacheable
であるにもかかわらず、キャッシュ ヒットがない場合は、コマンドラインに--noremote_accept_cached
が含まれている可能性があります。この場合、ビルドのキャッシュ検索が無効になります。実際のコマンドラインを特定するのが難しい場合は、Build Event Protocol の正規のコマンドラインを次のように使用します。
a. ログのテキスト バージョンを取得するには、
--build_event_text_file=/tmp/bep.txt
を Bazel コマンドに追加します。b. ログのテキスト バージョンを開き、
command_line_label: "canonical"
を含むstructured_command_line
メッセージを検索します。展開すると、すべてのオプションが一覧表示されます。c.
remote_accept_cached
を検索し、false
に設定されているかどうかを確認します。d.
remote_accept_cached
がfalse
の場合は、false
に設定されている場所(コマンドラインまたは bazelrc ファイル)を特定します。
マシン間のキャッシュ保存を保証する
同じマシンでキャッシュ ヒットが想定どおりに発生したら、別のマシンで同じビルド / テストを実行します。マシン間でキャッシュ保存が行われていないと思われる場合は、次の操作を行います。
既存のキャッシュにヒットしないように、ビルドに小さな変更を加えます。
最初のマシンでビルドを実行します。
bazel clean
bazel ... build ... --execution_log_compact_file=/tmp/exec1.log
2 台目のマシンでビルドを実行し、ステップ 1 の変更が含まれていることを確認します。
bazel clean
bazel ... build ... --execution_log_compact_file=/tmp/exec2.log
2 つの実行の実行ログを比較します。ログが同一でない場合は、ビルド構成の不一致と、ホスト環境のプロパティがどちらかのビルドに漏洩しているかどうかを調査します。
実行ログを比較する
実行ログには、ビルド中に実行されたアクションの記録が含まれています。各レコードは、入力(ファイルだけでなく、コマンドライン引数、環境変数など)とアクションの出力の両方を記述します。したがって、ログを調べると、アクションが再実行された理由がわかります。
実行ログは、コンパクト(--execution_log_compact_file
)、バイナリ(--execution_log_binary_file
)、JSON(--execution_log_json_file
)の 3 つの形式のいずれかで生成できます。コンパクト形式は、ランタイム オーバーヘッドが非常に少なく、ファイルサイズが大幅に小さくなるため、推奨されます。以下の手順は、どの形式でも使用できます。//src/tools/execlog:converter
ツールを使用して、これらの間で変換することもできます。
キャッシュ ヒットが想定どおりに共有されていない 2 つのビルドのログを比較するには、次の操作を行います。
各ビルドから実行ログを取得し、
/tmp/exec1.log
と/tmp/exec2.log
として保存します。Bazel ソースコードをダウンロードして、
//src/tools/execlog:parser
ツールをビルドします。git clone https://github.com/bazelbuild/bazel.git cd bazel bazel build //src/tools/execlog:parser
//src/tools/execlog:parser
ツールを使用して、ログを人が読めるテキスト形式に変換します。この形式では、2 番目のログのアクションが 1 番目のログの順序と一致するように並べ替えられるため、比較が容易になります。bazel-bin/src/tools/execlog/parser \ --log_path=/tmp/exec1.log \ --log_path=/tmp/exec2.log \ --output_path=/tmp/exec1.log.txt \ --output_path=/tmp/exec2.log.txt
お好みのテキスト差分ツールを使用して、
/tmp/exec1.log.txt
と/tmp/exec2.log.txt
の差分を比較します。