如何实现从一个进程到另一个进程的快速上下文切换?

2024-03-26

我需要在沙箱进程上运行不安全的本机代码,并且需要减少进程切换的瓶颈。两个进程(控制器和沙箱)共享两个自动重置events http://msdn.microsoft.com/en-us/library/windows/desktop/aa964766(v=vs.85).aspx以及用于通信的映射文件(共享内存)的连贯视图。

为了使本文更精简,我从示例代码中删除了初始化,但事件由控制器创建,使用 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()- 550ms,~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做了类似的事情,但我只发现本文档 https://sites.google.com/a/chromium.org/dev/nativeclient/reference/anatomy-of-a-sys。如果您有更多信息,请告诉我。


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

或者,由于您使用的是 2 核系统,因此使用自旋锁 http://en.wikipedia.org/wiki/Spinlock而不是事件会让你的代码更快,但代价是系统性能和功耗:

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 时间。

理想情况下,您应该使用混合方法。当一侧要忙一段时间时,让另一侧等待某个事件,以便其他进程可以获得一些 CPU 时间。您可以提前一点触发该事件(使用自旋锁来保持同步),以便其他线程在您准备好时准备好。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何实现从一个进程到另一个进程的快速上下文切换? 的相关文章

  • 查找用户输入中的第一个和最后一个大写字母

    输入将从 a z 或 A Z 中获取 并且输入以星号结束 我们需要将输入字符的第一个和最后一个大写字母作为输出 另外 我们应该显示每次输入的内容 注意 我们逐个字符地获取输入 而不是作为字符串 测试用例1 输入 aAbCcP 输出 AP 测
  • SLURM 节点、任务、核心和 CPU

    有人能够澄清这些东西到底是什么吗 据我所知 节点是集群内的计算点 本质上是一台计算机 任务是可以在单个节点或多个节点上执行的进程 核心基本上是指您希望在单个节点上分配多少 CPU 来执行分配给该 CPU 的任务 它是否正确 我混淆了什么吗
  • 由于图形处理单元配置,不支持 Windows Phone 模拟器(Mac 上的 Windows 7)

    启动 Windows Phone 模拟器时出现错误 不支持 Windows Phone 模拟器 因为您的计算机没有所需的图形处理单元配置 如果没有图形处理单元 XNA 框架页面将无法运行 您想继续启动模拟器吗 当我尝试访问网页 任何网页 时
  • 如何从 Android 调用 RESTful 方法?

    我尝试了两种不同的方法来从 Android 调用简单的 REST 方法 所述 REST 方法 适用于其他客户端 仅返回一个 int val 例如 17 以下两次尝试都是基于我在网上找到的代码 有一种是这样的 公共无效onFetchBtnCl
  • 以编程方式从 java 代码中查找 java.exe 的绝对路径

    如果我有一个由用户启动的 java jar 或类文件 假设在环境变量中设置了 java 路径 那么我如何从代码中找出 java exe javaw exe 的绝对路径文件正在启动 就像在 ubuntu 上一样 我们可以运行 which ja
  • iPhone 应用程序中的异步、同步、线程

    我正处于一个应用程序的设计阶段 该应用程序将利用 REST Web 服务 并且在使用异步 同步和线程方面遇到了困境 这是场景 假设您有三个选项可供深入研究 每个选项都有自己的基于 REST 的资源 我可以使用同步请求延迟加载每个请求 但这会
  • Vim 在 Mingw 上表现异常

    我在 MinGW 4 6 2 上的 Vim 表现得很奇怪 例如 在插入模式下按 Backspace 会删除字符 但我必须用箭头键移动光标才能删除的字符消失 而且它也会使我退出插入模式 另一个例子 按 Del 删除字符有时会生成奇怪的字符 例
  • 使用 gcc 在 Linux 上运行线程构建块 (Intel TBB)

    我正在尝试为线程构建块构建一些测试 不幸的是 我无法配置 tbb 库 链接器找不到库 tbb 我尝试在 bin 目录中运行脚本 但这没有帮助 我什至尝试将库文件移动到 usr local lib 但这又失败了 任何的意见都将会有帮助 确定您
  • Hazelcast 分布式锁与 iMap

    我们目前使用 Hazelcast 3 1 5 我有一个简单的分布式锁定机制 应该可以跨多个 JVM 节点提供线程安全性 代码非常简单 private static HazelcastInstance hInst getHazelcastIn
  • 如何将 GIT 调用的输出获取到批处理脚本中的变量中?

    我有一个 git 命令来获取当前存储库的最新 SHA 如下所示 git log pretty format H n 1 我有一个 Windows 批处理脚本 我想按如下方式使用它 SET CURRENT SHA 但我不知道如何将从 git
  • 如何从Windows阻止社交媒体[关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我想根据时间阻止我的电脑上的社交媒体 晚上 9 点后屏蔽 上午 11 点后解锁 如家长控制 我尝试过关注但失败了 创建了
  • Interlocked.CompareExchange 的返回值是否有一些充分的理由

    The Interlocked CompareExchange 方法 docs https learn microsoft com en us dotnet api system threading interlocked comparee
  • 从 64 位 nasm 代码接收 32 位寄存器

    我正在学习 64 位 nasm 我通过执行以下操作来汇编 nasm 文件 该文件仅包含 64 位寄存器 nasm f elf64 HelloWorld nasm o HelloWorld o 并链接它执行以下操作 ld HelloWorld
  • 防止重入并确保某些操作获取锁的正确方法是什么?

    我正在设计一个基类 当继承该基类时 它将针对多线程环境中的上下文提供业务功能 每个实例可能都有长时间运行的初始化操作 所以我想让这些对象可重用 为此 我需要能够 为这些对象之一分配上下文以允许其完成工作 防止对象在已有上下文的情况下被分配新
  • 调用 printf 系统子例程在汇编代码中输出整数错误[重复]

    这个问题在这里已经有答案了 来回 在windows7控制台窗口中运行gcc s2 asm 然后生成一个exe文件 运行a exe 然后崩溃 为什么 s2 asm 代码由以下源代码生成 int m m 1 iprint m s2 asm请参考
  • 如何创建可获取数字的小矮人计算机 (LMC) 代码。奇数时显示1,偶数时显示0

    我的研究需要帮助 如果数字是偶数 它可以显示 1 如果数字是奇数 它可以显示 0 例如 如果输入是 99 它将显示输出 1 这意味着奇数 如果我显示 10 它将显示输出 0 这意味着偶数 我没有任何代码 因为我不知道如何开始 请帮忙 我对这
  • 不在焦点时响应键盘? (C#、Vista)

    我正在尝试编写一个应用程序 只要按下 Shift 键 无论当前哪个应用程序具有焦点 它都会做出响应 我尝试过这个SetWindowsHookEx 与GetKeyboardState 但这两种方法仅在应用程序窗口具有焦点时才有效 我需要它在全
  • 使用 async/await 抛出和捕获异常的正确方法

    全部请拿下面的二维码 Task
  • Final字段的线程安全

    假设我有一个 JavaBeanUser这是从另一个线程更新的 如下所示 public class A private final User user public A User user this user user public void
  • asp.net core / kestrel中的线程管理

    我正在解决我们已迁移到 asp net core 2 0 的 asp net 应用程序的性能 可扩展性问题 我们的应用程序作为应用程序服务托管在 azure 上 并且在任何中等流量的情况下都很容易崩溃 让我困惑的一件事是如何处理多个并发请求

随机推荐