我需要在沙盒进程上运行不安全的本机代码,并且需要减少进程切换的瓶颈。两个进程(控制器和沙箱)共享两个自动重置事件和用于通信的映射文件(共享内存)的一致视图。
为了使这篇文章更小,我从示例代码中删除了初始化,但事件由控制器创建,使用 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 毫秒,约 350k 上下文切换,42% CPU(25% 内核,17% 用户)。inProcess()
- 20ms,~2k 上下文切换,55% CPU(2% 内核,53% 用户)。
该机器是Windows 7 Pro,Core 2 Duo P9700,内存为8gb。
一个有趣的事实是,沙盒解决方案使用了 42% 的 CPU 与 55% 的进程内解决方案。另一个值得注意的事实是沙盒解决方案包含 350k 上下文切换,这比我们可以从源代码中推断出的 200k 上下文切换要多得多。
我需要知道是否有办法减少将控制转移到另一个进程的开销。我已经尝试使用管道而不是事件,而且情况更糟。我还尝试完全不使用任何事件,方法是在每个请求上进行沙盒调用SuspendThread(GetCurrentThread())
和控制器调用ResumeThread(hSandboxThread)
,但性能类似于使用事件。
如果您有使用程序集(例如执行手动上下文切换)或 Windows 驱动程序工具包的解决方案,也请告诉我。我不介意必须安装驱动程序来加快速度。
我听说 Google Native Client 做了类似的事情,但我只找到了这个文档。如果您有更多信息,请告诉我。