只使用一个文件描述符,select、poll和epoll有性能差异吗?

14

标题已经说明了一切。

“...”也包括pselect和ppoll。

我正在处理一个基于多线程的服务器项目。每个线程处理一个或多个会话。所有线程都是相同的。协议负责确定哪个线程将托管会话。

我正在使用一个内部套接字类来封装事物。值得注意的是checkread调用,它调用poll(Linux)或select(Windows)。

总之,每个线程当前对单个套接字调用poll。从我所看到的情况来看,仅当此线程查看多个套接字时,例如在HTTP服务器中可以获得的内容时,使用epoll才会有益处。这不是我在本例中所做的。而且该类一次只处理一个套接字。

在epoll的man页面中有关于边沿和水平触发的简短讨论。我不是很确定这是什么意思。在套接字类中,我在代码的Windows部分中看到一种优化,通过ioctlsocket&FIONREAD来快捷地跳过选择调用,以检查是否有任何数据。想知道即使在调用时没有完整的UDP数据包是否到达,这是否会返回> 0。这就是epoll中边缘触发的含义吗?

在一些基本测试中,我也看不到使用select和poll之间的明显差异。

我可以看到使用ppoll可能会有好处,因为它具有更高的超时精度。你有什么想法吗?

是的,我正在尝试优化接收大量数据的会话的吞吐量。服务器比CPU更受网络和磁盘约束。

3个回答

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具有一些开销,但只有一个套接字没有用)。

谢谢,这基本上证实了我通过试验所发现的内容。 - hookenz
2
如果单个文件描述符数量很大,您不想使用select,因为selectO(max fd number),而pollO(number of fds in the request) - o11c

5

0

如果你只有一个套接字,那么轮询的意义是什么呢?难道最好的性能不是使用阻塞读/写吗?

关于性能,对于只有一个文件描述符,我认为各种方法之间没有太大的区别,如果有的话也微乎其微。如果你真的在意,我想你可以进行测量,但我觉得这对你程序的整体性能并不特别重要。

级别/边缘触发。考虑你正在监视一个信号,为简单起见,假设是某条线路上的电压。边缘触发意味着当电压超过或低于某个特定限制时会触发某些事件。级别触发意味着只要电压超过/低于限制,就被认为处于触发状态。也就是说,边缘触发在某些事件发生时触发(越过某个阈值),级别触发反映了某个“事物”的状态(在这种情况下是电压)。

回到网络编程,边缘触发系统可能是一种在收到数据包时获得某种信号的系统。如果你不处理该事件,则信号将丢失。另一方面,级别触发系统是一种类似于询问“是否有数据在缓冲区等待我?”的系统;如果你不处理该事件并再次询问,则数据仍将在那里等待你。


2
通过使用轮询,我可以在同一线程内设置超时并进行其他工作。当没有其他事情可做并且我正在等待来自网络的数据时,我也可以使用轮询来阻塞。我可以创建另一个线程,但这会带来共享数据等其他问题。在我的情况下,更多的线程意味着更复杂,并没有任何好处。我尝试了很多方法。 - hookenz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接