このページでは、多重化ワーカー、多重化互換ルールを記述する方法、特定の制限事項の回避策について説明します。
多重化ワーカーを使用すると、Bazel は 1 つのワーカー プロセスで複数のリクエストを処理できます。マルチスレッド ワーカーの場合、Bazel はより少ないリソースで同等以上のパフォーマンスを実現できます。たとえば、Bazel では、ワーカーごとに 1 つのワーカー プロセスを用意するのではなく、同じワーカー プロセスと通信する 4 つの多重化ワーカーを用意し、リクエストを並行して処理できます。Java や Scala などの言語の場合、これにより JVM のウォームアップ時間と JIT コンパイル時間が短縮され、一般に同じタイプのすべてのワーカー間で 1 つの共有キャッシュを使用できます。
概要
Bazel サーバーとワーカー プロセスの間には 2 つのレイヤがあります。プロセスを並行して実行できる特定のニーモニックの場合、Bazel はワーカープールから WorkerProxy
を取得します。WorkerProxy
は、request_id
とともにリクエストをワーカー プロセスに順番に転送します。ワーカー プロセスはリクエストを処理し、WorkerMultiplexer
にレスポンスを送信します。WorkerMultiplexer
はレスポンスを受信すると、request_id
を解析し、正しい WorkerProxy
にレスポンスを転送します。非多重化ワーカーと同様に、すべての通信は標準の入出力で行われますが、ツールはユーザーに表示される出力に stderr
を使用することはできません(下記を参照)。
各ワーカーにはキーがあります。Bazel は、キーのハッシュコード(環境変数、実行ルート、ニーモニックで構成される)を使用して、使用する WorkerMultiplexer
を決定します。WorkerProxy
は、ハッシュコードが同じであれば、同じ WorkerMultiplexer
と通信します。したがって、1 回の Bazel 呼び出しで環境変数と実行ルートが同じであると仮定すると、一意のニーモニックごとに 1 つの WorkerMultiplexer
と 1 つのワーカー プロセスしか存在できません。レギュラー ワーカーと WorkerProxy
を含むワーカーの合計数は、引き続き --worker_max_instances
によって制限されます。
多重化対応ルールの作成
多重ワーカーを活用するには、ルールのワーカー プロセスをマルチスレッドにする必要があります。Protobuf を使用すると、ストリームに複数のリクエストが積み重なっている場合でも、ルールセットで 1 つのリクエストを解析できます。ワーカー プロセスがストリームからリクエストを解析するたびに、新しいスレッドでリクエストを処理する必要があります。異なるスレッドが同時に完了してストリームに書き込む可能性があるため、ワーカー プロセスはレスポンスがアトミックに書き込まれるようにする必要があります(メッセージが重複しないようにします)。レスポンスには、処理しているリクエストの request_id
が含まれている必要があります。
多重化された出力の処理
マルチプレックス ワーカーは、シングルプレックス ワーカーよりも出力の処理に注意する必要があります。stderr
に送信されたものは、同じタイプのすべての WorkerProxy
で共有される単一のログファイルに記録され、同時リクエスト間でランダムにインターリーブされます。stdout
を stderr
にリダイレクトするのは良い方法ですが、その出力を WorkResponse
の output
フィールドに収集しないでください。ユーザーに破損した出力が表示される可能性があります。ツールがユーザー向けの出力を stdout
または stderr
にのみ送信する場合は、多重化ワーカーを有効にする前にその動作を変更する必要があります。
多重化ワーカーを有効にする
多重化ワーカーはデフォルトでは有効になっていません。ルールセットでは、アクションの execution_requirements
で supports-multiplex-workers
タグを使用して、多重ワーカーを有効にできます(supports-workers
タグで通常のワーカーを有効にするのと同様です)。通常のワーカーを使用する場合と同様に、ルールセット レベル(--strategy=[some_mnemonic]=worker
など)または一般的に戦略レベル(--dynamic_local_strategy=worker,standalone
など)でワーカー戦略を指定する必要があります。追加のフラグは必要ありません。supports-multiplex-workers
と supports-workers
の両方が設定されている場合は、supports-multiplex-workers
が supports-workers
よりも優先されます。--noworker_multiplex
を渡すことで、多重化ワーカーをグローバルにオフにできます。
ルールセットでは、メモリ負荷を軽減し、パフォーマンスを向上させるため、可能な限り多重ワーカーを使用することが推奨されます。ただし、マルチプレックス ワーカーは、マルチプレックス サンドボックスを実装しない限り、現在のところ動的実行と互換性がありません。動的実行でサンドボックス化されていないマルチプレックス ワーカーを実行しようとすると、代わりにサンドボックス化されたシングルプレックス ワーカーが使用されます。
Multiplex のサンドボックス化
ワーカー実装で明示的なサポートを追加することで、多重ワーカーをサンドボックス化できます。シングルプレックス ワーカーのサンドボックス化は、各ワーカー プロセスを独自のサンドボックスで実行することで実現できますが、マルチプレックス ワーカーは、複数の並列リクエスト間でプロセス作業ディレクトリを共有します。多重化ワーカーのサンドボックス化を許可するには、ワーカーが作業ディレクトリに直接読み書きするのではなく、各リクエストで指定されたサブディレクトリに読み書きすることをサポートする必要があります。
多重サンドボックスをサポートするには、ワーカーは WorkRequest
から sandbox_dir
フィールドを使用し、それをすべてのファイルの読み取りと書き込みの接頭辞として使用する必要があります。arguments
フィールドと inputs
フィールドはサンドボックス化されていないリクエストから変更されませんが、実際の入力は sandbox_dir
に相対的です。ワーカーは、arguments
と inputs
で見つかったファイルパスを変換して、この変更されたパスから読み取る必要があります。また、すべての出力を sandbox_dir
を基準とした相対パスで書き込む必要があります。これには、'.' などのパスのほか、引数で指定されたファイル(「argfile」引数など)で見つかったパスも含まれます。
ワーカーが多重サンドボックスをサポートすると、ルールセットはアクションの execution_requirements
に supports-multiplex-sandboxing
を追加することで、このサポートを宣言できます。--experimental_worker_multiplex_sandboxing
フラグが渡された場合、またはワーカーが動的実行で使用されている場合、Bazel は多重サンドボックスを使用します。
サンドボックス化された多重ワーカーのワーカー ファイルは、ワーカー プロセスの作業ディレクトリを基準とする相対パスのままです。したがって、ワーカーの実行と入力の両方にファイルが使用される場合は、フラグファイル引数の入力として、tools
、executable
、runfiles
の両方で指定する必要があります。