使用单个文件描述符,select,poll和epoll与......之间是否有任何性能差异?

时间:2011-04-13 10:09:47

标签: c++ sockets select epoll

标题真的说明了一切。

和...意味着还包括pselect和ppoll ..

我正在处理的服务器项目基本上是用多个线程构建的。每 线程处理一个或多个会话。所有线程都是相同的。协议 负责哪个线程将主持会话。

我正在使用一个包装内容的内部套接字类。感兴趣的点是一个checkread调用,它调用poll(linux)或select(windows)。

总之,每个线程当前在单个套接字上调用poll。据我所知,如果这个线程正在查看多个套接字,例如你在HTTP服务器中得到的东西,那么使用epoll只会有好处。那不是我在做的事情。并且该类一次只处理一个套接字。

在epoll的手册页中有一些关于边缘和级别触发的简短讨论。我不太确定这意味着什么。在socket类中,我看到代码的windows部分中的优化,它使用ioctlsocket& amp;来快速切换select调用。 FIONREAD检查是否有任何数据。想知道是否会返回> 0即使在呼叫时没有到达完整的UDP数据包也是如此。这是epoll的边缘触发吗?

在一些基本测试中,我也发现使用select和poll之间没有明显的区别。

我可以看到使用ppoll可能会有所帮助,因为超时的精度更高。有什么想法吗?

是的,我正在尝试优化接收大量数据的会话的吞吐量。服务器更像网络&磁盘绑定比CPU。

3 个答案:

答案 0 :(得分:7)

epoll与select或poll之间的主要区别在于epoll在单个线程中运行时可以更好地扩展。我不知道这与使用select或poll的多线程服务器相比如何。 看看这个http://monkey.org/~provos/libevent/libevent-benchmark2.jpg

这个原因(据我所知)是当你使用select或poll时,你必须遍历所有连接的套接字以确定哪些有要读取的数据。当你使用epoll时,它会保留一个单独的数组,其中只包含对有数据要读取的套接字的引用。这样可以节省大量的循环周期,并且连接的插座越多,差异就会越来越明显。

如果性能成为一个主要问题,另一个需要考虑的是io完成端口(仅限Windows)和kqueue(仅限FreeBSD)。记住epoll只是linux也很重要。在大多数情况下,select或poll可以正常工作。

在单个文件描述符的情况下,select和poll比epoll 更有效,因为它更简单。 (epoll有一些开销,只有一个插槽才能使它自己有用)

答案 1 :(得分:4)

根据链接:http://www.intelliproject.net/articles/showArticle/index/io_multiplexing

如果只使用一个描述符:

  • select:201微秒。
  • poll:159微秒。
  • epoll:176微秒。

在这种情况下,似乎poll将是更好的解决方案。

答案 2 :(得分:0)

如果你只有一个插座,首先是什么轮询?那么最佳性能不是仅仅使用阻塞读/写吗?

WRT。性能,只有一个文件描述符,我不认为各种方法之间存在太多(如果有的话)差异。如果你真的在乎,我想你可以衡量一下,但我发现这对于你的计划的整体表现来说特别重要。

等级/边缘触发。考虑一下您正在监控一个信号,为简单起见,请说明一线电压。边沿触发意味着当电压超过或低于某个特定限制时触发某事。电平触发意味着只要电压超过/低于限制,某些事物就被认为处于触发状态。也就是说,边缘触发在某些事件发生时触发(超过某个阈值),电平触发反映某些“事物”的状态(在这种情况下,电压)。

要回到网络编程,边缘触发系统可能是收到数据包时会收到某种信号的系统。如果您不处理该事件,则信号将丢失。水平触发系统OTOH就像是在询问“缓冲区中有数据等待我吗?”;如果您不处理该事件并再次询问,数据仍将在那里等着您。