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