動的実行

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

動的実行は、Bazel の機能です。ローカル リモート実行では、最初に完了したブランチの出力を使用して他のブランチをキャンセルし、同じアクションを並列実行します。リモート ビルドシステムの実行能力や大規模な共有キャッシュとローカル実行の低レイテンシを兼ね備え、クリーンなビルドとインクリメンタルなビルドの両方で両方の長所を提供します。

このページでは、動的実行を有効化、調整、デバッグする方法について説明します。ローカルとリモートの両方の実行が設定され、Bazel の設定を調整してパフォーマンスを改善しようとしている場合は、このページをご覧ください。リモート実行をまだ設定していない場合は、最初に Bazel リモート実行の概要に移動します。

動的実行を有効にしますか?

動的実行モジュールは Bazel の一部ですが、動的実行を利用するには、同じ Bazel 設定からローカルとリモートの両方でコンパイルできる必要があります。

動的実行モジュールを有効にするには、--internal_spawn_scheduler フラグを Bazel に渡します。これにより、dynamic という新しい実行戦略が追加されます。--strategy=Javac=dynamic など、動的に実行する略語の戦略としてこれを使用できます。動的実行を有効にするニーモニックを選択する方法については、次のセクションをご覧ください。

動的戦略を使用する略語では、リモート実行戦略は --dynamic_remote_strategy フラグ、ローカル戦略は --dynamic_local_strategy フラグから取得されます。--dynamic_local_strategy=worker,sandboxed を渡すと、動的実行のローカル ブランチのデフォルトが、その順序でワーカーまたはサンドボックス実行によって試行されるように設定されます。--dynamic_local_strategy=Javac=worker を渡すと、Java ニーモニックでのみデフォルト値がオーバーライドされます。リモコンの動作も同じです。両方のフラグを複数回指定できます。ローカルで実行できないアクションは、通常どおりリモートで実行されます。その逆も同様です。

リモート システムにキャッシュがある場合、--dynamic_local_execution_delay フラグを使用すると、リモート システムがキャッシュ ヒットを示した後、ローカル実行にミリ秒単位で遅延が追加されます。これにより、より多くのキャッシュ ヒットが発生する可能性が高い場合にローカル実行を回避できます。デフォルト値は 1, 000 ミリ秒ですが、通常キャッシュ ヒットより少し長めに設定してください。実際の時間は、リモート システムとラウンドトリップにかかる時間によって異なります。ラウンドトリップ レイテンシが遠く離れている場合を除き、この値は特定のリモート システムのすべてのユーザーで同じになります。Bazel プロファイリング機能を使用して、通常のキャッシュ ヒットにかかった時間を確認できます。

動的実行は、ローカル サンドボックス戦略や永続ワーカーで使用できます。永続ワーカーを動的実行で使用すると、サンドボックス化は自動的に実行されます。Multiplex ワーカーは使用できません。Darwin と Windows のシステムでは、サンドボックス化戦略は時間がかかる可能性があります。--reuse_sandbox_directories を渡すと、これらのシステムでサンドボックス作成のオーバーヘッドを削減できます。

動的実行は standalone 戦略で実行することもできますが、standalone 戦略は実行開始時に出力ロックを受け取る必要があるため、リモート戦略が最初に終了するのを効果的にブロックします。この問題を回避するには、--experimental_local_lockfree_output を実行することで、ローカル実行が出力に直接書き込めるようにしますが、リモート実行によって最初に終了した場合は中断します。

動的実行のブランチのいずれかが最初に終了し、失敗すると、アクション全体が失敗します。これは、ローカル実行とリモート実行の違いに気づかないようにすることを目的としたものです。

動的実行とそのロックの仕組みについて詳しくは、Jioio Merino の優れたブログ投稿をご覧ください。

どのような場合に動的実行を使用すればよいですか?

動的実行には、なんらかのリモート実行システムが必要です。キャッシュミスはアクションの失敗とみなされるため、現時点ではキャッシュのみのリモート システムは使用できません。

すべての種類のアクションがリモート実行に適しているわけではありません。最良の候補は、永続ワーカーの使用など、本質的にローカルで高速に動作するノードや、リモート実行のオーバーヘッドが実行時間の大半を占める高速実行候補です。ローカルで実行される各アクションは、ある量の CPU リソースとメモリリソースをロックします。そのため、そのようなカテゴリに分類されないアクションの実行は、遅延実行の実行を遅らせるだけです。

リリース 5.0.0-pre.20210708.4 では、パフォーマンス プロファイリングに、ワーカーの実行に関するデータ(動的実行の競合を失った後の処理リクエストの終了時間など)が含まれています。動的実行ワーカー スレッドがリソースの取得にかなりの時間がかかる、または async-worker-finish で多くの時間がかかる場合は、ワーカー スレッドを遅延させる低速なローカル アクションが発生している可能性があります。

動的な実行パフォーマンスが低いデータのプロファイリング

8 つの Javac ワーカーを使用する上記のプロファイルでは、多くの Javac ワーカーが競合を失い、async-worker-finish スレッドでの作業を終了しています。これは、ワーカー以外の用語でワーカーの遅延が発生するのに十分なリソースが原因で発生しました。

動的な実行パフォーマンスの向上によるデータのプロファイリング

動的実行で Javac のみを実行すると、開始ワーカーの約半分のみが作業の開始後にレースを失います。

以前に推奨されていた --experimental_spawn_scheduler フラグは非推奨になりました。これにより動的実行が有効になり、dynamic がすべてのニーモニックのデフォルト戦略に設定されます。そのため、このような問題が発生する可能性があります。

パフォーマンス

動的実行のアプローチでは、ローカルとリモートで十分なリソースが利用可能であり、全体的なパフォーマンスを向上させるために追加リソースを使用する価値があることを前提としています。ただし、リソースが過剰に使用された場合、Bazel やマシンの実行速度が低下したり、リモート システムに想定外の負荷がかかったりするおそれがあります。動的実行の動作を変更するには、いくつかの方法があります。

--dynamic_local_execution_delay は、リモート ブランチの開始後、ローカル ブランチの開始を数ミリ秒遅らせます。ただし、現在のビルド中にリモート キャッシュ ヒットが発生した場合に限ります。これにより、リモート キャッシュを利用するビルドは、ほとんどの出力がキャッシュで見つかる可能性があってもローカル リソースを無駄にしなくなります。キャッシュの品質によっては、この速度を下げることで、ビルド速度を向上させることができますが、ローカル リソースの使用量が増えます。

--experimental_dynamic_local_load_factor は試験運用版の高度なリソース管理オプションです。0 ~ 1 の値を取り、この機能をオフにします。 0 より大きい値に設定すると、Bazel が多数のアクションのスケジューリングを待機している場合に、ローカルでスケジュールされるアクションの数を調整します。1 に設定すると、使用可能な CPU の数だけアクションがスケジュールされます(--local_cpu_resources による)。値が小さいほど、実行できるアクションの数が増えるほど、それに応じてスケジュールされるアクションの数が少なくなります。これは直感的に聞こえないかもしれませんが、優れたリモート システムでは、ローカル実行は多くのアクションが実行されているときにあまり役に立たず、ローカル CPU はリモート アクションの管理に費やされる可能性が高くなります。

--experimental_dynamic_slow_remote_time は、リモート ブランチが少なくとも長時間実行されている場合、ローカル ブランチの開始を優先します。通常、レースに勝つ可能性が最も高いため、最新のスケジュール済みアクションが優先されますが、リモート システムがハングアップしたり、より長い時間をかけていたりすると、ビルドが進む可能性があります。これは修正すべきリモート システムの問題を非表示にする可能性があるため、デフォルトでは有効になっていません。このオプションを有効にする場合は、リモート システムのパフォーマンスを必ずモニタリングしてください。

--experimental_dynamic_ignore_local_signals を使用すると、特定のシグナルが原因でローカルでスポーンが終了したときに、リモート ブランチに引き継ぐことができます。これは主に、リソースが多すぎるとワーカー プロセスが強制終了される可能性のあるワーカー リソース上限(--experimental_worker_memory_limit_mb--experimental_worker_sandbox_hardening--experimental_sandbox_memory_limit_mbと併せて有用です。

JSON トレース プロファイルには、パフォーマンスとリソース使用量のトレードオフを改善する方法を特定できる、パフォーマンス関連のグラフが多数含まれています。

トラブルシューティング

動的実行に関する問題は、ローカル実行とリモート実行の特定の組み合わせでのみ検出されるため、デバッグが困難な場合があります。--debug_spawn_scheduler は、動的実行システムからの出力を追加して、これらの問題のデバッグに役立てます。問題を再現しやすくするために、--dynamic_local_execution_delay フラグと、リモートジョブまたはローカルジョブの数を調整することもできます。

standalone 戦略を使用した動的実行で問題が発生した場合は、--experimental_local_lockfree_output なしで実行するか、サンドボックス化したローカル アクションを実行してください。これにより、ビルドが少し遅くなる可能性があります(Mac または Windows を使用している場合は上記参照)。ただし、失敗の原因はいくつか考えられます。