select/轮询与Twisted中的epoll反应器的注意事项

我所阅读和经历的一切(基于Tornado的应用程序)使我相信,ePoll是Select和Pollnetworking的自然替代品,特别是Twisted。 这使我偏执,这是一个更好的技术或方法,而不是一个价格。

阅读epoll和替代品之间的几十个比较表明,epoll显然是速度和可伸缩性的冠军,特别是它以线性的方式缩放,这是非常棒的。 那么说,处理器和内存使用率呢,epoll还是冠军?

对于非常小的套接字(当然,取决于您的硬件,但我们正在谈论的东西大约10或更less),select可以击败内存使用率和运行时速度epoll。 当然,对于这样less数的套接字,这两种机制都是如此之快,以至于在绝大多数情况下,你并不关心这种差异。

一个澄清,虽然。 select和epoll线性缩放。 不同的是,面向用户空间的API具有基于不同事物的复杂性。 select调用的成本大致与通过它的最高编号的文件描述符的值相同。 如果你select一个单一的fd,100,那么这个花费大约是select一个单一的fd,50的两倍。在最高点以下添加更多的fds并不是很自由,所以这比实际中的复杂一点,但是这个对大多数实现来说是一个很好的初步近似。

epoll的成本更接近实际上有事件的文件描述符的数量。 如果您正在监视200个文件描述符,但其中只有100个文件描述符有事件,那么您(非常粗略地)只支付这100个活动文件描述符。 这是epoll倾向于提供超过select的主要优点之一。 如果你有一千个大多数闲置的客户,那么当你使用select的时候,你仍然要为这一千个客户付钱。 然而,与epoll,就像你只有几个 – 你只支付那些在任何时候活跃的。

所有这一切意味着epoll会导致大多数工作负载的CPU使用率降低。 至于内存使用情况,这是一个有点折腾。 select可以设法以高度紧凑的方式表示所有必要的信息(每个文件描述符一位)。 FD_SETSIZE(通常为1024)限制你可以使用多less个文​​件描述符,这意味着你可以在select (read,write,exception)中使用三个fd集合,每个永远不会超过128个字节。 相比于那些384字节的最大值,epoll就像是一头猪。 每个文件描述符都由多字节结构表示。 但绝对而言,它仍然不会占用太多的内存。 你可以用几十千字节来表示大量的文件描述符(大约每1000个文件描述符有20k,我认为)。 而且,如果你只想监视一个文件描述符,但是它的值恰好是1024,那么你必须花费所有这384个字节的事实,如果你只花了20个字节。 不过,所有这些数字都很小,所以没有太大的差别。

epoll的另一个好处,也许你已经知道,它不限于FD_SETSIZE文件描述符。 您可以使用它来监视尽可能多的文件描述符。 如果你只有一个文件描述符,但是它的值大于FD_SETSIZE,那么epoll也可以工作,但是select不会。

随机地,我最近还发现了一个与selectpoll相比epoll有一点小缺点。 虽然这三个API都不支持普通文件(即文件系统上的文件),但是selectpoll当前缺乏支持,因为报告这些描述符始终可读且始终可写。 这使得它们不适合任何有意义的非阻塞文件系统I / O,一个使用selectpoll的程序,碰巧遇到来自文件系统的文件描述符将至less继续运行(或者如果失败,它不会是因为selectpoll ),虽然它可能不是最好的performance。

另一方面,当被要求监视这样的文件描述符时, epoll将会快速失败并且出现错误( EPERM ,显然)。 严格来说,这是不正确的。 这只是表明缺乏明确的支持。 通常我会赞扬明确的失败条件,但是这个没有logging(据我所知),并导致一个完全破坏的应用程序,而不是一个仅仅在可能降级的性能下运行的应用程序。

在实践中,我见过的唯一的地方就是与stdio互动。 用户可能会将标准input或标准输出从/redirect到普通文件。 而之前的stdin和stdout本来就是一个由epoll支持的pipe道 – 然后它变成了一个普通的文件,epoll失败了,打破了应用程序。

在我公司的testing中,出现了一个与epoll()相关的问题,因此与select相比成本较高。

当试图从networking读取超时时,创buildepoll_fd(而不是FD_SET),并将fd添加到epoll_fd,比创build一个FD_SET(这是一个简单的malloc)要昂贵得多。

根据以前的答案,随着过程中FD的数量变大,select()的成本变高,但在我们的testing中,即使在10,000的fd值,select仍然是赢家。 这些情况下只有一个线程正在等待的fd,并且只是试图克服在使用阻塞线程模型时networking读取和networking写入不超时的事实。 当然,与非阻塞反应堆系统相比,阻塞螺纹模型的性能较差,但有些情况下需要与特定的遗留代码库集成。

这种用例在高性能应用程序中很less见,因为反应器模型不需要每次都创build一个新的epoll_fd。 对于epoll_fd长期存在的模型—对于任何高性能的服务器devise来说这显然是首选— epoll在各方面都是明显的赢家。