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

問題を報告する ソースを表示

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

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

キャッシュ ヒット率を確認する

Bazel 実行の標準出力で、プロセスを一覧表示する INFO 行を確認します。これは、Bazel アクションにほぼ対応します。その行は、アクションが実行された場所の詳細を示しています。リモートで実行されるアクションを示す remote ラベル、ローカル サンドボックスで実行されるアクションを示す linux-sandbox、その他の実行戦略用の他の値を探します。結果がリモート キャッシュからのアクションの場合、remote cache hit と表示されます。

次に例を示します。

INFO: 11 processes: 6 remote cache hit, 3 internal, 2 remote.

この例では、リモート キャッシュ ヒットが 6 回発生しています。アクションはキャッシュ ヒットがなく、リモートで実行されています。3 の内部部分は無視できます。これは通常、シンボリック リンクの作成などの小さな内部アクションです。ローカル キャッシュ ヒットは、この概要には含まれません。プロセスが 0 個(または想定よりも小さい数)取得された場合は、bazel clean の次に build/test コマンドを実行します。

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

想定したキャッシュ ヒット率が表示されない場合は、次の手順を行います。

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

  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 が同じで、キャッシュ ヒットがない場合は、構成が原因でキャッシュ保存が妨げられています。このセクションを続行して、一般的な問題を確認してください。

    実行ログの差分を表示する必要がない場合は、人が読める形式の --execution_log_json_file フラグを使用できます。実行時間が含まれ、順序が保証されないため、安定した差分処理には使用できません。

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

  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 の場合は、false に設定されている場所(コマンドラインまたは bazelrc ファイル)を確認します。

マシン全体で確実にキャッシュする

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

  1. 既存のキャッシュにヒットしないように、ビルドを微調整します。

  2. 最初のマシンでビルドを実行します。

     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 の差分を異なるものにします。