Windows:基于事件的重叠 IO 与 IO 完成端口,真实世界性能

Windows: Event-based Overlapped IO vs IO Completion Ports, Real World Performance

所以我一直在研究我正在构建的服务器应用程序的套接字的重叠 IO,并且我不断看到人们的评论说 "never use hEvent" 或 "IO completion ports will be faster" 等,但没有人曾经说过为什么不使用 hEvent 并且没有人提供任何关于完成端口更快或更快的真实世界数据或数字。 hEventWaitForMultipleObjects() 更适合我的应用程序,所以如果速度差异很小,我倾向于使用它,但我不想在没有一些真实数据告诉我有多大的情况下承诺这样做我在那里做出的牺牲。我用谷歌搜索了又搜索又搜索,除了一些 Whosebug 的回答说 "don't use this one" 没有给出理由之外,找不到任何基准或文章或任何比较这两种策略的东西。

任何人都可以在这里提供一些关于使用 hEvent 和完成端口之间的实际差异的真实信息或数字吗?

这个答案源自 Harry Johnston 作为对该问题的评论,经过一些搜索,我发现了一些使 WaitForMultipleObjects 成为一件可怕的事情的更多细节。

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

In NT terms, to enter the wait, a wait block has to be allocated for every object, and each waitblock is queued to the object you're waiting for and then cross-linked to the thread. When any of those objects are signalled all those wait blocks have to be dequeued, unlinked, and deallocated back to pool. All of that happens at DISPATCH_LEVEL and all except the pool allocation and free happens with the dispatcher spinlock held.

(WFMO with fAll == TRUE is even MORE expensive. Every time ANY of the objects is signalled, all the others have to be checked. This all happens, you guessed it, at DISPATCH_LEVEL with the dispatcher spinlock held.)

调度程序级别的自旋锁可防止整个系统中线程的抢占和时间片,即使是多核也是如此。如果你正在等待超过 3 个对象,那是一个永远不要使用 WFMO 的好理由(线程有 3 个预分配的等待块,如果你正在等待,可以避免很多3 个或更少)。

为了获得最佳性能,您应该使用 IO 完成端口。插座数量没有限制。所有其他 select-like api 将仅服务 1024 个套接字,性能将下降 rapidly,以及高于需要的 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 流的任何事情变得不切实际。