gpt4 book ai didi

multithreading - 非阻塞 I/O 真的比多线程阻塞 I/O 更快吗?如何?

转载 作者:行者123 更新时间:2023-12-03 04:41:36 26 4
gpt4 key购买 nike

我在网上搜索了一些有关阻塞 I/O 和非阻塞 I/O 的技术细节,发现有几个人说非阻塞 I/O 会比阻塞 I/O 更快。例如this document .

如果我使用阻塞 I/O,那么当前被阻塞的线程当然不能做任何其他事情......因为它被阻塞了。但是,一旦一个线程开始被阻塞,操作系统就可以切换到另一个线程,并且在被阻塞的线程有事情可做之前不会切换回来。因此,只要系统上有另一个线程需要 CPU 并且未被阻塞,与基于事件的非阻塞方法相比,就不应该有更多的 CPU 空闲时间,是吗?

除了减少 CPU 空闲时间之外,我还看到了增加计算机在给定时间范围内可以执行的任务数量的另一种选择:减少切换线程带来的开销。但这怎么办呢?开销是否足够大以显示可测量的效果?以下是我如何想象它的工作原理:

  1. 要加载文件的内容,应用程序将此任务委托(delegate)给基于事件的 I/O 框架,并传递回调函数和文件名
  2. 事件框架委托(delegate)给操作系统,操作系统对硬盘的 DMA Controller 进行编程,将文件直接写入内存
  3. 事件框架允许运行更多代码。
  4. 完成磁盘到内存的复制后,DMA Controller 会引发中断。
  5. 操作系统的中断处理程序通知基于事件的 I/O 框架文件已完全加载到内存中。它是如何做到的?使用信号??
  6. 当前在事件 I/O 框架内运行的代码完成。
  7. 基于事件的 I/O 框架检查其队列并查看第 5 步中的操作系统消息,并执行第 1 步中获得的回调。

是这样的吗?如果没有,它是如何工作的?这意味着事件系统可以工作而无需显式接触堆栈(例如真正的调度程序需要备份堆栈并将另一个线程的堆栈在切换线程时复制到内存中)?这实际上节省了多少时间?还有更多吗?

最佳答案

非阻塞或异步 I/O 的最大优点是您的线程可以继续并行工作。当然,您也可以使用额外的线程来实现这一点。正如您所说的最佳整体(系统)性能,我想最好使用异步 I/O 而不是多个线程(因此减少线程切换)。

让我们看看一个网络服务器程序的可能实现,该程序应处理 1000 个并行连接的客户端:

  1. 每个连接一个线程(可以是阻塞 I/O,也可以是非阻塞 I/O)。
    每个线程都需要内存资源(还有内核内存!),这是一个缺点。每个额外的线程都意味着调度程序需要做更多的工作。
  2. 一个线程用于所有连接。
    这会占用系统负载,因为我们的线程较少。但它也会阻止您充分利用机器的性能,因为您最终可能会将一个处理器驱动到 100%,而让所有其他处理器闲置。
  3. 几个线程,每个线程处理一些连接。
    由于线程较少,这会占用系统负载。它可以使用所有可用的处理器。在 Windows 上,Thread Pool API 支持此方法。 .

当然,拥有更多线程本身并不是问题。正如您可能已经认识到的那样,我选择了相当多的连接/线程。如果我们只讨论十几个线程,我怀疑您是否会看到三种可能的实现之间有任何差异(这也是 Raymond Chen 在 MSDN 博客文章 Does Windows have a limit of 2000 threads per process? 中建议的内容)。

在 Windows 上使用 unbuffered file I/O意味着写入的大小必须是页面大小的倍数。我还没有测试过它,但听起来这也可能对缓冲同步和异步写入的写入性能产生积极影响。

您描述的步骤 1 到 7 很好地了解了其工作原理。在 Windows 上,操作系统将使用事件或回调通知您异步 I/O(带有 OVERLAPPED 结构的 WriteFile)的完成情况。仅当您的代码调用 WaitForMultipleObjectsEx 并将 bAlertable 设置为 true 时,才会调用回调函数。

在网上阅读更多内容:

关于multithreading - 非阻塞 I/O 真的比多线程阻塞 I/O 更快吗?如何?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8546273/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com