Multiplex ワーカー(試験運用版)

問題を報告 ソースを表示

このページでは、マルチプレックス ワーカー、マルチプレックスと互換性のあるルールの作成方法、特定の制限の回避策について説明します。

Multiplex ワーカーを使用すると、Bazel は単一のワーカー プロセスで複数のリクエストを処理できます。マルチスレッド ワーカーの場合、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 呼び出しで同じ場合、一意の各ニモニックに設定できる WorkerMultiplexer とワーカー プロセスは 1 つのみです。通常のワーカーと WorkerProxy を含むワーカーの合計数は、引き続き --worker_max_instances によって制限されます。

Multiplex 互換ルールの作成

マルチプレックス ワーカーを利用するには、ルールのワーカー プロセスをマルチスレッドにする必要があります。ストリームに複数のリクエストが蓄積した場合でも、Protobuf はルールセットが 1 つのリクエストを解析できるようにします。ワーカー プロセスがストリームからのリクエストを解析するたびに、新しいスレッドでリクエストを処理する必要があります。異なるスレッドが完了してストリームへの書き込みが同時に行われる可能性があるため、ワーカー プロセスはレスポンスがアトミックに書き込まれるようにする必要があります(メッセージは重複しません)。レスポンスには、処理するリクエストの request_id を含める必要があります。

Multiplex 出力の処理

Multiplex ワーカーは、シングルプレックス ワーカーよりも出力の処理に注意を払う必要があります。stderr に送信されたものはすべて、同じタイプのすべての WorkerProxy で共有される 1 つのログファイルに入り、同時リクエスト間でランダムにインターリーブされます。stdoutstderr にリダイレクトすることはおすすめしますが、その出力を WorkResponseoutput フィールドに収集しないでください。ユーザーがマングリングした出力が表示される可能性があります。ツールがユーザー指向の出力を stdout または stderr にのみ送信する場合は、マルチプレックス ワーカーを有効にする前に、この動作を変更する必要があります。

Multiplex ワーカーの有効化

Multiplex ワーカーはデフォルトでは有効になっていません。ルールセットでは、アクションの execution_requirementssupports-multiplex-workers タグを使用して、Multiplex ワーカーを有効にできます(supports-workers タグで通常のワーカーを有効にするのと同様)。通常のワーカーを使用する場合と同様に、ワーカー戦略はルールセット レベル(--strategy=[some_mnemonic]=worker など)または通常は戦略レベル(--dynamic_local_strategy=worker,standalone など)で指定する必要があります。追加のフラグは不要です。両方が設定されている場合、supports-multiplex-workerssupports-workers よりも優先されます。グローバルでマルチプレックス ワーカーを無効にするには、--noexperimental_worker_multiplex を渡します。

ルールセットでは、メモリ プレッシャーを軽減し、パフォーマンスを改善するために、可能であれば Multiplex ワーカーを使用することをおすすめします。ただし、現在、Multiplex ワーカーには、Multiplex サンドボックスを実装していない限り、動的実行との互換性がありません。サンドボックス化されていない多重化ワーカーを動的実行で実行しようとすると、代わりにサンドボックス化されたシングルプレックス ワーカーが暗黙的に使用されます。

Multiplex サンドボックス

Multiplex ワーカーは、ワーカー実装に明示的なサポートを追加することでサンドボックス化できます。単一プレックス ワーカーのサンドボックス化は、各ワーカー プロセスを独自のサンドボックスで実行することによって実行できますが、マルチプレックス ワーカーは複数の並列リクエスト間でプロセスの作業ディレクトリを共有します。マルチプレックス ワーカーのサンドボックス化を許可するには、ワーカーが作業ディレクトリで直接行うのではなく、各リクエストで指定されたサブディレクトリに対する読み取りと書き込みをサポートする必要があります。

多重化サンドボックスをサポートするには、ワーカーで WorkRequestsandbox_dir フィールドを使用し、すべてのファイルの読み取りと書き込みの接頭辞として使用する必要があります。arguments フィールドと inputs フィールドはサンドボックス化されていないリクエストから変更されませんが、実際の入力は sandbox_dir からの相対値になります。ワーカーは、argumentsinputs にあるファイルパスを変換して、変更されたパスから読み取る必要があります。また、sandbox_dir を基準として相対的にすべての出力を書き込む必要があります。「.」などのパスや、引数で指定されたファイル内のパス("argfile" 引数など)が含まれます。

ワーカーが多重化サンドボックスをサポートすると、ルールセットはアクションの execution_requirementssupports-multiplex-sandboxing を追加することで、このサポートを宣言できます。--experimental_worker_multiplex_sandboxing フラグが渡された場合、またはワーカーが動的実行で使用されている場合、Bazel は多重サンドボックス化を使用します。

サンドボックス化された多重化ワーカーのワーカー ファイルは、引き続きワーカー プロセスの作業ディレクトリを基準とします。したがって、ファイルがワーカーの実行と入力の両方で使用される場合は、flagfile 引数と toolsexecutablerunfiles の両方で入力として指定する必要があります。