このページでは、多重化ワーカー、多重化に対応したルールの記述方法、特定の制限事項の回避策について説明します。
多重化ワーカーを使用すると、Bazel は 1 つのワーカー プロセスで複数のリクエストを処理できます。マルチスレッド ワーカーの場合、Bazel はより少ないリソースで同等以上のパフォーマンスを実現できます。たとえば、ワーカーごとに 1 つのワーカー プロセスを用意するのではなく、Bazel は同じワーカー プロセスと通信する 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
を使用すると、ストリームに複数のリクエストが積み重なっている場合でも、ルールセットは単一のリクエストを解析できます。ワーカー プロセスがストリームからリクエストを解析するたびに、新しいスレッドでリクエストを処理する必要があります。異なるスレッドが同時に完了してストリームに書き込む可能性があるため、ワーカー
プロセスはレスポンスがアトミックに書き込まれるようにする必要があります(メッセージが重複しないようにします)。レスポンスには、処理するリクエストの
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 より優先されます。--noworker_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
の両方で指定する必要があります。