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

时间:2010-01-09 06:39:04

标签: networking scalability twisted capacity-planning

我所阅读和体验过的所有内容(基于Tornado的应用程序)让我相信ePoll是基于Select和Poll的网络的自然替代品,尤其是Twisted。这让我变得偏执,对于更好的技术或方法来说,这是非常罕见的,而不是为了付出代价。

阅读epoll和替代品之间的几十个比较表明,epoll显然是速度和可扩展性的支柱,特别是它以线性方式扩展,非常棒。那说,处理器和内存利用率如何,epoll仍然是冠军?

2 个答案:

答案 0 :(得分:184)

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

但是,有一个澄清。选择和epoll线性地缩放。但是,一个很大的区别是面向用户空间的API具有基于不同事物的复杂性。 select调用的成本大致与您传递的最高编号文件描述符的值相近。如果你选择一个单独的fd,100,那么这大约是选择单个fd的两倍,50。添加更多fds低于最高值并不是很自由,所以它在实践中比这更复杂,但是这个对于大多数实现来说,它是一个很好的第一近似值。

epoll的成本更接近实际上有事件的文件描述符的数量。如果您正在监视200个文件描述符,但只有100个文件描述符,那么您(非常粗略地)只支付这100个活动文件描述符。这就是epoll倾向于提供其优于SELECT的主要优势之一。如果你有一千个大多数闲置的客户,那么当你使用select时,你仍然需要支付全部一千个。然而,对于epoll,就像你只有一些 - 你只需支付那些在任何特定时间都活跃的那些。

所有这些意味着epoll将导致大多数工作负载的CPU使用率降低。就内存使用而言,它有点折腾。 select确实设法以高度紧凑的方式表示所有必要的信息(每个文件描述符一位)。对于select可以使用多少个文​​件描述符的FD_SETSIZE(通常为1024)限制意味着您可以使用select的三个fd集中的每一个都不会花费超过128个字节(读,写,异常)。与最大384个字节相比,epoll有点像猪。每个文件描述符由多字节结构表示。但是,从绝对意义上说,它仍然不会占用太多内存。您可以用几十千字节表示大量的文件描述符(我认为大约每1000个文件描述符20k)。如果你只想监视一个文件描述符但它的值恰好是1024,那么你还可以投入这样一个事实:你必须花费select这些字节中的所有384个字节,而epoll你只需花费20字节。尽管如此,所有这些数字都非常小,所以它没有多大区别。

还有epoll的其他好处,也许你已经知道,它不仅限于FD_SETSIZE文件描述符。您可以使用它来监视尽可能多的文件描述符。如果你只有一个文件描述符,但它的值大于FD_SETSIZE,epoll也可以使用它,但select没有。

epollselect相比,我最近发现了poll的一个轻微缺点。虽然这三个API都不支持普通文件(即文件系统上的文件),但selectpoll表示缺乏支持,因为报告此类描述符始终可读且始终可写。这使得它们不适用于任何有意义的非阻塞文件系统I / O,使用selectpoll并碰巧遇到来自文件系统的文件描述符的程序将至少继续运行(或如果它失败了,那不会是因为selectpoll),尽管它可能没有最好的表现。

另一方面,当epoll被要求监视此类文件描述符时,EPERM将快速失败并显示错误({{1}})。严格来说,这几乎不正确。它只是以明确的方式表明它缺乏支持。通常情况下,我会为明确的失败条件鼓掌,但是这个条款没有记录(据我所知)并导致完全破坏的应用程序,而不是仅仅运行可能性能下降的应用程序。

在实践中,我见过这个唯一的地方就是在与stdio交互时。用户可能将stdin或stdout从/向正常文件重定向。以前stdin和stdout本来是一个管道 - 由epoll支持就好了 - 然后它变成了一个普通文件,epoll大声失败,打破了应用程序。

答案 1 :(得分:4)

在我公司的测试中,出现了epoll()的一个问题,因此与select相比只有一个成本。

当尝试从网络读取超时时,创建epoll_fd(而不是FD_SET),并将fd添加到epoll_fd,比创建FD_SET(这是一个简单的malloc)要贵得多。

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

这种用例在高性能应用程序中很少见,因为反应器模型不需要每次都创建新的epoll_fd。对于epoll_fd长寿的模型 - 这显然是任何高性能服务器设计的首选 - epoll在各方面都是明显的赢家。