サンドボックス プロセスで安全でないネイティブ コードを実行する必要があり、プロセス切り替えのボトルネックを減らす必要があります。両方のプロセス (コントローラとサンドボックス) は、2 つの自動リセットイベントと、通信に使用されるマップされたファイル (共有メモリ) の一貫したビューを共有します。
この記事を小さくするために、サンプル コードから初期化を削除しましたが、イベントはコントローラーによって作成され、DuplicateHandle を使用して複製され、作業前にサンドボックス プロセスに送信されます。
コントローラ ソース:
void inSandbox(HANDLE hNewRequest, HANDLE hAnswer, volatile int *shared) {
int before = *shared;
for (int i = 0; i < 100000; ++i) {
// Notify sandbox of a new request and wait for answer.
SignalObjectAndWait(hNewRequest, hAnswer, INFINITE, FALSE);
}
assert(*shared == before + 100000);
}
void inProcess(volatile int *shared) {
int before = *shared;
for (int i = 0; i < 100000; ++i) {
newRequest(shared);
}
assert(*shared == before + 100000);
}
void newRequest(volatile int *shared) {
// In this test, the request only increments an int.
(*shared)++;
}
サンドボックス ソース:
void sandboxLoop(HANDLE hNewRequest, HANDLE hAnswer, volatile int *shared) {
// Wait for the first request from controller.
assert(WaitForSingleObject(hNewRequest, INFINITE) == WAIT_OBJECT_0);
for(;;) {
// Perform request.
newRequest(shared);
// Notify controller and wait for next request.
SignalObjectAndWait(hAnswer, hNewRequest, INFINITE, FALSE);
}
}
void newRequest(volatile int *shared) {
// In this test, the request only increments an int.
(*shared)++;
}
測定:
inSandbox()
- 550 ミリ秒、~35 万のコンテキスト スイッチ、42% の CPU (25% のカーネル、17% のユーザー)。inProcess()
- 20ms、~2k コンテキストスイッチ、55% CPU (2% カーネル、53% ユーザー)。
マシンは Windows 7 Pro、Core 2 Duo P9700、メモリ 8 GB です。
興味深い事実は、サンドボックス ソリューションが CPU の 42% を使用するのに対し、インプロセス ソリューションの 55% を使用することです。もう 1 つの注目すべき事実は、サンドボックス ソリューションに 35 万のコンテキスト スイッチが含まれていることです。これは、ソース コードから推測できる 20 万のコンテキスト スイッチよりもはるかに多い数です。
別のプロセスへの転送制御のオーバーヘッドを削減する方法があるかどうかを知る必要があります。私はすでにイベントの代わりにパイプを使用しようとしましたが、それははるかに悪いものでした. また、リクエストごとに サンドボックス呼び出しSuspendThread(GetCurrentThread())
とコントローラー呼び出しを行うことで、イベントをまったく使用しないようにしましたが、パフォーマンスはイベントを使用した場合と同様でした。ResumeThread(hSandboxThread)
アセンブリ (手動のコンテキスト スイッチの実行など) または Windows Driver Kit を使用するソリューションがある場合は、私にもお知らせください。これを高速化するためにドライバーをインストールする必要はありません。
Google Native Client も同様のことをしていると聞きましたが、このドキュメントしか見つかりませんでした。さらに詳しい情報をお持ちの場合は、お知らせください。