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

問題を報告 ソースを表示

このページでは、Multiplex ワーカー、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 が同じハッシュコードを持つ場合、WorkerProxy は同じ WorkerMultiplexer と通信します。したがって、1 回の Bazel 呼び出しで環境変数と実行ルートが同じであると仮定すると、固有のニーモニックごとに WorkerMultiplexer とワーカー プロセスは 1 つだけになります。通常のワーカーや WorkerProxy を含むワーカーの合計数は、引き続き --worker_max_instances によって制限されます。

Multiplex 互換ルールの記述

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

マルチプレックス出力の処理

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

Multiplex ワーカーを有効にする

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

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

Multiplex サンドボックス化

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

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

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

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