我们有针对1到50左右的描述符范围的基准测试吗?我看到的大多数基准都是针对大量描述符100的。。1000秒。。。
我目前正在使用带有16个描述符的民意调查,如果这能提高应用程序的速度,我会考虑使用epoll。
Please advise in 3 scenarios with 16 socket descriptors in the set for poll/epoll:
1. most of the sockets are active...>both should be same performance?
2. half active half idle....what is better here?
3. mostly idle...> clearly epoll is better ?
我非常怀疑从poll()
切换到epoll()
不会对应用程序的性能产生任何影响。当您有许多文件描述符(数百或数千个)时,epoll()
的主要优势就会显现出来,其中标准的poll()
每次调用都需要做更多的工作,而epoll()
会提前进行设置-只要您不更改正在观看的文件描述符集,每次调用都会稍微快一点。但一般来说,这种差异只有在很多文件描述符中才明显。
请记住,如果您正在观察的文件描述符集频繁更改,epoll()
的主要优势就会丧失,因为您仍然需要将新的文件描述符传递到内核中。因此,如果你正在处理大量短暂的连接,那么切换到它就更没有吸引力了
另一个区别是,epoll()
可以是边缘触发,其中只有当描述符上出现新活动时调用才会返回,也可以是级别触发别触发。然而,对于大多数人来说,级别触发是他们想要的——边缘触发接口偶尔会有用,但在大多数情况下,它们会导致竞争条件,即数据在读取后但在进入epoll()
调用之前到达套接字。我的建议是远离边缘触发代码,除非你真的、真的知道自己在做什么。
为epoll()
付出的代价是缺乏可移植性——poll()
和select()
都是标准的POSIX接口,因此使用它们将使代码更加可移植。另一方面,epoll()
调用仅在Linux上可用。其他一些Unix变体也有自己的等效机制,例如FreeBSD上的kqueue,但在这种情况下,您必须为每个平台编写不同的代码。
我的建议是,在您使用许多文件描述符之前,甚至不要担心epoll()
——说真的,在您的代码中几乎可以肯定还有许多其他地方可以进行更大的性能改进,而且epoll()
对您的用例来说可能不会更快。
如果您确实达到了处理许多连接的阶段,并且您的代码的其余部分已经非常优化,那么您应该首先考虑像libev这样的东西,它是一个跨平台接口,在每个特定平台上使用最佳性能调用。它的性能非常好,总体上可能比直接使用epoll()
要麻烦得多,即使您只想支持Linux。
到目前为止,我还没有提到你提到的三种场景,因为我不相信它们中的任何一种对于少量的文件描述符(如16)会有任何不同的表现。对于大量的文件描述符,epoll()
应该优于poll()
,特别是在大部分空闲文件描述符的情况下。如果所有文件描述符都是活动的,那么两个调用都需要遍历每个连接来处理它。然而,随着空闲连接比例的增加,epoll()
只返回活动连接,因此性能更好-使用poll()
,您仍然需要遍历所有连接,并且大多数连接都将被跳过,但epoll()
只返回您需要处理的内容(最多可以指定一个最大限制)。
要明确说明这一点(正如我上面提到的,这仅与大量连接相关):
- 大多数套接字都是活动的:这两个调用大致相当,也许
epoll()
仍然稍微领先 - 半活动半空闲:希望
epoll()
在这里会更好 - 大部分空闲:希望
epoll()
在这里肯定会更好
编辑:
您可能希望看到这张来自libevent作者的图,它显示了随着文件描述符数量的变化,处理事件的相对开销。注意所有的线是如何围绕原点聚合的,这表明所有的机制对于少量的描述符都实现了可比较的性能。