【问题标题】:Windows: Event-based Overlapped IO vs IO Completion Ports, Real World PerformanceWindows:基于事件的重叠 IO 与 IO 完成端口,真实世界的性能
【发布时间】:2017-06-20 23:26:37
【问题描述】:

所以我一直在研究我正在构建的服务器应用程序的套接字的重叠 IO,并且我不断看到人们说“永远不要使用hEvent”或“IO 完成端口会更快”等等,但没有人说过为什么不使用hEvent,也没有人提供任何关于完成端口更快或更快的真实数据或数字。 hEventWaitForMultipleObjects() 更适合我的应用程序,所以如果速度差异很小,我倾向于使用它,但如果没有一些真实数据告诉我我有多大的牺牲,我不想承诺正在那里制作。除了一些 StackOverflow 回答说“不要使用这个”而没有给出任何理由之外,我已经搜索和搜索并找不到任何基准或文章或任何比较这两种策略的东西。

谁能在这里提供一些真实的信息或数字,说明使用 hEvent 和完成端口之间的实际区别?

【问题讨论】:

  • 这是关于减少线程数的。如果您使用单个WaitForMultipleObjects 来等待您的所有I/O,那么这基本上与I/O 完成端口相同。您不希望每个 I/O 操作都有自己的WaitForSingleObject,因为这意味着每个待处理的 I/O 操作都需要自己的线程,doesn't scale
  • 对,我完全可以理解WaitForSingleObject 绝对不会扩展。我想象WaitForMultipleObjects 在这种情况下扮演与epoll 类似的角色,尽管我确实意识到存在很大差异。我也可以理解完成端口如何比WaitForMultipleObjects 略有优势,但如果优势很小,我更喜欢WaitForMultipleObjects 方法,因为它可以更好地(感知)我的应用程序中的线程控制。
  • 请记住,使用 WaitForMultipleObjects 会将您限制为每个线程 64 个客户端。您期望同时连接多少个?
  • 说“从不使用hEvent”的人需要给出一个理由。否则建议是无用的。
  • @HarryJohnston 真的吗?这就是MAXIMUM_WAIT_OBJECTS 是什么?这是不使用它的一个很好的理由——我实际上还没有开始编写代码,只是查看了文档,并认为MAXIMUM_WAIT_OBJECTS 会是......一些合理的东西。谢谢你终于给了一个很好的理由! (而且我只是明确表示我主要不是 Windows 开发人员。:))

标签: c++ windows winsock winsock2


【解决方案1】:

这个答案来自 Harry Johnston 作为对该问题的评论,经过一番搜索,我发现了一些让 WaitForMultipleObjects 变得可怕的细节。

您可以等待的最大对象数为 64。仅此一项就使得 WFMO 方法的可扩展性几乎不存在。但进一步看,我发现了这个帖子:https://groups.google.com/forum/#!topic/comp.os.ms-windows.programmer.win32/okwnsYetF6g

在 NT 术语中,要进入等待,a 必须为每个对象分配等待块,每个等待块是 排队到您正在等待的对象,然后交叉链接到 线。当任何这些对象发出信号时,所有这些等待块 必须出列、取消链接并重新分配回池。所有的 发生在 DISPATCH_LEVEL,除了池分配和空闲 发生在调度程序自旋锁被持有的情况下。

(fAll == TRUE 的 WFMO 甚至更贵。每次 对象发出信号后,必须检查所有其他对象。这一切 您猜对了,发生在 DISPATCH_LEVEL 与调度程序自旋锁 举行。)

调度程序级别的自旋锁可防止整个系统中的线程抢占和时间片,即使是多核也是如此。如果您等待超过 3 个对象(线程预分配了 3 个等待块,如果您等待 3 个或更少)。

【讨论】:

  • 调度程序自旋锁has not existed since Windows 7,因此不再需要对调度程序自旋锁的担忧。
  • 很高兴知道。不过,仍然值得关注,因为很多人仍在使用 Windows 7。
  • Windows 7 已修复。仍然有调度程序锁的是 Windows Vista。
  • 啊,好的,抱歉。我误解了。 :)
【解决方案2】:

为了获得最佳性能,您应该使用 IO 完成端口。套接字的数量没有限制。所有其他 select-like api 将仅服务 1024 个套接字,性能将迅速下降,同时 CPU 使用率会高于所需。

https://msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx

您还可以查看这个关于异步 i/o 的精彩演示,我认为对于任何打算编写中型到大型客户端服务器应用程序的人来说,这是必看的。

时间的历史:异步 C++ - Steven Simpson [ACCU 2017] https://www.youtube.com/watch?v=Z8tbjyZFAVQ

在此演示文稿中,您将找到对可用技术的完整描述和比较,以及基准测试结果。非常值得花时间。

WaitForMultipleObjects() 限制为 64 个句柄,这使得处理涉及多个 i/o 流的任何事情变得不切实际。

【讨论】:

  • 当然,类似于 select 的 API 有问题,但我没有问他们。 :) 我已经知道 select()、poll() 等的问题。这个问题具体是关于与重叠 IO 交互的两种方式(这两种方式都是异步的、非阻塞的,并且不使用 select-像 API):IO 完成端口与在 OVERLAPPED 结构上设置 hEvent 对象。感谢您提供的信息——但您实际上并没有在这里谈论WaitForMultipleObjects...
  • WaitForMultipleObjects 不是一种可行的 I/O 方式。比select还差,
  • 我看到其他网站有不同的说法,但没有人给出任何实际原因或任何实际数据。我见过一些网站说“重叠 IO 是最好的(完成端口除外,它甚至更好)”。然后我看到其他人说“不要使用WFMO”。如果您阅读我帖子的内容,我的问题不是“我应该使用哪个”,而是“有人可以给我一些真实的数字以及为什么一个比另一个更好的原因吗?”正如 Raymond Chen 所说,在没有给出理由的情况下说“不要使用它”并不是特别有用的建议。 (也就是说,如果你看看我自己的答案,我找到了原因。)
  • 换句话说,这个问题不是在寻求建议,而是在寻求理解。我知道人们建议使用哪一个,但我想知道为什么,我想知道差异有多大。 IOCPselect() 之间的比较很多,但 IOCP 和其他处理重叠 IO 的方法之间没有比较。我希望实际数据能够让我自己做出明智的结论,而不是假设互联网是正确的。
  • 它没有讨论 WaitForMultipleObjects 因为它甚至不被认为是一个可行的解决方案。正如每个人告诉你的那样。 epoll 和 io 完成端口的性能相当,因为这两个 API 访问相同的底层技术,尽管针对不同的操作系统。
猜你喜欢
  • 1970-01-01
  • 2014-02-08
  • 1970-01-01
  • 2021-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-15
  • 1970-01-01
相关资源
最近更新 更多