如何使从一个进程到另一个快速上下文切换? [英] How to make a fast context switch from one process to another?

查看:488
本文介绍了如何使从一个进程到另一个快速上下文切换?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要在沙箱中运行的过程不安全本土code,我需要减少进程切换的瓶颈。这两个过程(控制器和沙箱)的股票两种自动复位的 事件和映射文件(共享内存)的一致观点,即用于通信。

I need to run unsafe native code on a sandbox process and I need to reduce bottleneck of process switch. Both processes (controller and sandbox) shares two auto-reset events and a coherent view of a mapped file (shared memory) that is used for communication.

为了使这个小文章,我删除了从样品code初始化,但事件是由控制器创建的,使用DuplicateHandle复制,然后送到沙盒进程工作开始之前。

To make this article smaller, I removed initializations from sample code, but the events are created by the controller, duplicated using DuplicateHandle, and then sent to sandbox process prior to work.

控制器来源:

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() - 550ms,350K〜上下文切换,42%的CPU(25%的内核,17%的用户)。

  • 制程() - 20毫秒,2K〜上下文切换,55%的CPU(2%的内核,53%的用户)

  • inSandbox() - 550ms, ~350k context switches, 42% CPU (25% kernel, 17% user).
  • inProcess() - 20ms, ~2k context switches, 55% CPU (2% kernel, 53% user).

本机的Windows 7专业版,酷睿2 P9700 8GB内存。

The machine is Windows 7 Pro, Core 2 Duo P9700 with 8gb of memory.

这是有趣的事实是沙箱解决方案使用的CPU 42%对过程中的溶液的55%。另外一个值得注意的事实是,沙箱溶液含有350K上下文切换,这是比200k的上下文切换,我们可以从源$ C ​​$ C推断多

An interesting fact is that sandbox solution uses 42% of CPU vs 55% of in-process solution. Another noteworthy fact is that sandbox solution contains 350k context switches, which is much more than the 200k context switches that we can infer from source code.

我需要知道,如果有,以控制转移开销减少到另一个进程的一种方式。我已经尝试过使用管道,而不是事件,它是更糟糕。我也试图在所有使用任何情况下,通过沙箱调用 SuspendThread(GetCurrentThread()),使控制器调用 ResumeThread(hSandboxThread)在每次请求,但性能类似于使用事件。

I need to know if there's a way to reduce the overhead of transfer control to another process. I already tried to use pipes instead of events, and it was much worse. I also tried to use no event at all, by making the sandbox call SuspendThread(GetCurrentThread()) and making the controller call ResumeThread(hSandboxThread) on every request, but the performance was similar to using events.

如果您有使用组件(如执行手动上下文切换),或Windows驱动程序工具包的解决方案,请让我知道为好。我不介意安装驱动程序,使这个速度更快。

If you have a solution that uses assembly (like performing a manual context switch) or Windows Driver Kit, please let me know as well. I don't mind having to install a driver to make this faster.

我听说,谷歌本地客户端做类似的东西,但我只找到的本文档。如果您有更多的信息,请让我知道。

I heard that Google Native Client does something similar, but I only found this documentation. If you have more information, please let me know.

推荐答案

首先要尝试是提高等待的线程的优先级。这应该减少外来上下文切换的数量。

The first thing to try is raising the priority of the waiting thread. This should reduce the number of extraneous context switches.

另外,因为你是一个双核系统上,使用自旋锁而不是事件将使你的code得多快,在系统性能和功耗成本:

Alternatively, since you're on a 2-core system, using spinlocks instead of events would make your code much much faster, at the cost of system performance and power consumption:

void inSandbox(volatile int *lock, volatile int *shared) 
{
  int i, before = *shared;
  for (i = 0; i < 100000; ++i) {
    *lock = 1;
    while (*lock != 0) { }
  }
  assert(*shared == before + 100000);
}

void newRequest(volatile int *shared) {
  // In this test, the request only increments an int.
  (*shared)++;
}

void sandboxLoop(volatile int *lock, volatile int * shared)
{
  for(;;) {
    while (*lock != 1) { }
    newRequest(shared);
    *lock = 0;
  }
}

在这种情况下,你应该设置线程的亲和力口罩和/或降低纺纱线程的优先级,使其不与繁忙的线程CPU时间的竞争。

In this scenario, you should probably set thread affinity masks and/or lower the priority of the spinning thread so that it doesn't compete with the busy thread for CPU time.

在理想情况下,你会使用一种混合的方法。当一方将是热闹了一阵,让对方等待一个事件,以便其他进程可以得到一些CPU时间。你可以触发事件的时间有点超前(使用自旋锁保持同步),这样,当你在其他线程将准备。

Ideally, you'd use a hybrid approach. When one side is going to be busy for a while, let the other side wait on an event so that other processes can get some CPU time. You could trigger the event a little ahead of time (using the spinlock to retain synchronization) so that the other thread will be ready when you are.

这篇关于如何使从一个进程到另一个快速上下文切换?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆