リモート実行のためのリモート キャッシュ ヒットのデバッグ

問題を報告 ソースを表示 毎晩

このページでは、キャッシュ ヒット率を確認する方法と、リモート実行におけるキャッシュミスを調査する方法について説明します。

このページでは、リモート実行を正常に利用するビルドやテストがあり、リモート キャッシュを効果的に利用していることを前提としています。

キャッシュ ヒット率の確認

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 を実行してから、ビルド/テストコマンドを実行します。

キャッシュ ヒットのトラブルシューティング

期待するキャッシュ ヒット率が得られない場合は、次の操作を行います。

同じビルド/テストコマンドを再実行するとキャッシュ ヒットが発生することを確認する

  1. キャッシュにデータを入力する予定のビルドやテストを実行します。特定のスタックで新しいビルドを初めて実行するときは、リモート キャッシュ ヒットが発生しないことが予想されます。リモート実行の一環として、アクションの結果はキャッシュに保存され、後続の実行で結果が取得されます。

  2. bazel clean を実行します。このコマンドはローカル キャッシュをクリーンアップします。これにより、結果がローカル キャッシュ ヒットによってマスクされることなく、リモート キャッシュ ヒットを調査できます。

  3. 再調査するビルドとテストを(同じマシンで)実行します。

  4. INFO 行でキャッシュ ヒット率を確認します。remote cache hitinternal 以外のプロセスが表示されない場合は、キャッシュへのデータ入力とアクセスが正しく行われています。その場合は、次のセクションに進みます。

  5. 不一致の原因としては、ビルドに密閉型ではないものがあり、アクションが 2 つの実行で異なるアクションキーを受け取ることがあります。これらのアクションを確認する手順は次のとおりです。

    a. 問題のビルドまたはテストを再実行して実行ログを取得します。

      bazel clean
      bazel --optional-flags build //your:target --execution_log_binary_file=/tmp/exec1.log
    

    b. 2 つの実行間で実行ログを比較します。2 つのログファイルで操作が同一であることを確認します。不一致は、実行間で発生した変更についての手がかりとなります。ビルドを更新して、これらの不一致を解消します。

    キャッシュの問題を解決でき、繰り返し実行するとすべてのキャッシュ ヒットが生成された場合は、次のセクションに進みます。

    アクション ID が同一であるのにキャッシュ ヒットがない場合は、構成内のなんらかの原因によりキャッシュが妨げられています。次のセクションに進んで、一般的な問題を確認します。

  6. 実行ログのすべてのアクションで cacheable が true に設定されていることを確認します。特定のアクションの実行ログに cacheable が表示されない場合、対応するルールの BUILD ファイルの定義に no-cache タグがある可能性があります。実行ログの mnemonic フィールドと target_label フィールドを調べて、アクションの実行元を特定します。

  7. アクションが同一で 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_cachedfalse の場合は、コマンドラインまたは bazelrc ファイルで、false に設定されている場所を確認します。

マシン間でのキャッシュ保存を確認する

同じマシンでキャッシュ ヒットが想定どおりに発生したら、別のマシンで同じビルド / テストを実行します。マシン間でキャッシュが行われていないと思われる場合は、次の操作を行います。

  1. 既存のキャッシュにヒットしないように、ビルドに小さな変更を加えます。

  2. 1 台目のマシンでビルドを実行します。

     bazel clean
     bazel ... build ... --execution_log_binary_file=/tmp/exec1.log
    
  3. 2 台目のマシンでビルドを実行し、ステップ 1 の変更が含まれていることを確認します。

     bazel clean
     bazel ... build ... --execution_log_binary_file=/tmp/exec2.log
    
  4. 2 つの実行の実行ログを比較します。ログが同一でない場合は、ビルド構成に不一致がないか、ホスト環境のプロパティがいずれかのビルドに漏れていないか調べます。

実行ログの比較

実行ログには、ビルド中に実行されたすべてのアクションの記録が含まれます。アクションごとに、アクションキーのすべての情報を含む SpawnExec 要素があります。したがって、ログが同一であれば、アクション キャッシュキーも同じです。

想定どおりにキャッシュ ヒットを共有していない 2 つのビルドのログを比較する手順は次のとおりです。

  1. 各ビルドから実行ログを取得し、/tmp/exec1.log/tmp/exec2.log として保存します。

  2. 次のコマンドを使用して Bazel ソースコードをダウンロードし、Bazel フォルダに移動します。execlog パーサーで実行ログを解析するにはソースコードが必要です。

    git clone https://github.com/bazelbuild/bazel.git
    cd bazel
    
  3. 実行ログパーサーを使用してログをテキストに変換します。次の呼び出しでは、比較しやすくするために、2 番目のログのアクションが最初のログのアクション順序と一致するように並べ替えられます。

    bazel build src/tools/execlog:parser
    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
    
  4. 異なる任意のテキストを使用して、/tmp/exec1.log.txt/tmp/exec2.log.txt を比較します。