epoll与select/poll性能,CPU/内存开销对比stackoverflow上的一个精彩问答

Epoll 是 Linux 内核在2.5.44版本引进的一个新特性,旨在替换之前系统中老的 select, poll 等系统请求。这是 Linux I/O 系统一次质的飞跃。关于 Epoll 的详细的介绍见 Wikipedia

Epoll 在绝大多数情况下性能都远超 select 或者 poll,但是除了速度之外,三者之间的 CPU 开销,内存消耗情况又怎么样呢?

本文的内容来自 Stackoverflow 上一次精彩的问答,除了比较 poll, select 和 epoll 在性能,系统资源消耗等方面的差异之外,还指出了epoll 在对普通文件支持方面相对于 select/poll 的不足之处(当然,这三者本身都不支持普通文件,只是作者认为 epoll 对这类问题的处理机制不好,这是个见仁见智的事情,不代表作者的观点是正确的)。希望对这个Topic感兴趣的同学能够看完这篇文章,相信能使你对epoll有个更深的了解。

问:

Everything I’ve read and experienced ( Tornado based apps ) leads me to believe that ePoll is a natural replacement for Select and Poll based networking, especially with Twisted. Which makes me paranoid, its pretty rare for a better technique or methodology not to come with a price.

Reading a couple dozen comparisons between epoll and alternatives shows that epoll is clearly the champion for speed and scalability, specifically that it scales in a linear fashion which is fantastic. That said, what about processor and memory utilization, is epoll still the champ?

 

我读过和经历过的一切(龙卷风的应用程序)让我相信epoll是选择和民意调查为基础的网络自然的替代,特别是扭曲的。这让我偏执,它相当罕见的一个更好的技术或方法来不来的价格。
阅读epoll和替代品之间的比较表明,几十个epoll显然是速度和可扩展性的冠军,特别是它的尺度以线性方式这很神奇。就是说,什么是处理器和内存利用率,是实现依然是冠军吗?

  

 

答:

  

对sockets数量很小(取决于你的硬件,当然,但我们谈论的是在10个或更少的点),select能够击败epoll在内存使用和运行速度。当然,对于这样的小数目的sockets,这两种机制是如此之快,你不真的在乎这种差异在绝大多数情况下。
    但有一个澄清。无论是select和epoll的线性扩展。虽然有很大的不同,,是用户空间面临的API的复杂性,基于不同的东西。select调用的成本大致与您通过它传递的最高编号的文件描述符的值大致的值。如果你select一个单一的FD,100,那是大约两倍于一个单一的FDselect,50。添加更多的FDS低于最高的不是很自由,所以有点比这更复杂的实践中,但这是大多数实现一个良好的第一近似值。
    epoll成本接近文件描述符,实际上事件对他们的数量。如果您正在监视200个文件描述符,但只有100个文件描述符有事件,那么您(非常粗略地)只为那些100个活动的文件描述符支付。这就是epoll趋向提供它的一个主要优势select。如果你有一千个客户,大多是空闲的,那么当你使用select你仍然支付他们所有的一千。然而,随着epoll,它就像你只有几–你只付,在任何给定的时间是活跃的。
    所有这一切都意味着,epoll将导致大部分的工作更少的CPU使用率。就内存使用情况来说,这是一个有点折腾。select不管理代表所有必要的信息在一个高度紧凑的方式(一个位每文件描述符)。和fd_setsize(通常是1024)你可以使用select意味着你永远不会花超过128字节,每三个FD集可以使用与select多少文件描述符的限制(读,写,例外)。相比那些384字节的最大,epoll是猪类。每个文件描述符由一个多字节结构表示。然而,从绝对的角度来看,它仍然不会使用太多的内存。你可以代表数量庞大的几十KB的文件描述符(大约每1000
    20
    k文件描述符,我认为)。你也可以把这样的事实:你要花那384字节的select如果你只想监视一个文件描述符,但它的价值是1024,而用epoll你只花20个字节。然而,所有这些数字是相当小的,所以它并没有太大的差异。
    还有其他好处epoll,也许你已经注意到,它并不局限于fd_setsize文件描述符。您可以使用它来监视您所拥有的多个文件描述符。如果你只有一个文件描述符,但其值大于fd_setsize,epoll的作品,太,但select不。
    随机,最近我还发现了一个小缺点到epoll相比select或poll。虽然这三个API支持正常没有任何文件(一个文件系统即文件),select和调查目前缺乏这种支持报告描述符的可读性和可写的总是总是。这使得它们不适合任何有意义的一种非阻塞的文件系统I / O,一个程序使用select或poll,碰巧遇到一个文件描述符从文件系统至少会继续操作(或如果它失败了,它不会因为select或poll),尽管它可能不是最好的性能。
    另一方面,实现了将快速失败与错误(eperm,显然)当要求监视这样的文件描述符。严格地说,这几乎是不正确的。这只是表明它缺乏支持的一个明确的方式。通常情况下,我会鼓掌明确的失败条件,但这一个是非法的(据我所知)和结果在一个完全破碎的应用程序,而不是一个只是工作与潜在的性能退化。
    在实践中,我看到了这是唯一的地方是在互动的时候。一个用户可能重定向stdin或stdout从 / 到一个正常的文件。而此前stdin和stdout本来管由epoll蛮好的支持并成为一个正常的文件和epoll不大声,打破应用。
翻译

For very small numbers of sockets (varies depending on your hardware, of course, but we’re talking about something on the order of 10 or fewer), select can beat epoll in memory usage and runtime speed. Of course, for such small numbers of sockets, both mechanisms are so fast that you don’t really care about this difference in the vast majority of cases.

One clarification, though. Both select and epoll scale linearly. A big difference, though, is that the userspace-facing APIs have complexities that are based on different things. The cost of a select call goes roughly with the value of the highest numbered file descriptor you pass it. If you select on a single fd, 100, then that’s roughly twice as expensive as selecting on a single fd, 50. Adding more fds below the highest isn’t quite free, so it’s a little more complicated than this in practice, but this is a good first approximation for most implementations.

The cost of epoll is closer to the number of file descriptors that actually have events on them. If you’re monitoring 200 file descriptors, but only 100 of them have events on them, then you’re (very roughly) only paying for those 100 active file descriptors. This is where epoll tends to offer one of its major advantages over select. If you have a thousand clients that are mostly idle, then when you use select you’re still paying for all one thousand of them. However, with epoll, it’s like you’ve only got a few – you’re only paying for the ones that are active at any given time.

All this means that epoll will lead to less CPU usage for most workloads. As far as memory usage goes, it’s a bit of a toss up. select does manage to represent all the necessary information in a highly compact way (one bit per file descriptor). And the FD_SETSIZE (typically 1024) limitation on how many file descriptors you can use with select means that you’ll never spend more than 128 bytes for each of the three fd sets you can use with select (read, write, exception). Compared to those 384 bytes max, epoll is sort of a pig. Each file descriptor is represented by a multi-byte structure. However, in absolute terms, it’s still not going to use much memory. You can represent a huge number of file descriptors in a few dozen kilobytes (roughly 20k per 1000 file descriptors, I think). And you can also throw in the fact that you have to spend all 384 of those bytes with select if you only want to monitor one file descriptor but its value happens to be 1024, wheras with epoll you’d only spend 20 bytes. Still, all these numbers are pretty small, so it doesn’t make much difference.

And there’s also that other benefit of epoll, which perhaps you’re already aware of, that it is not limited to FD_SETSIZE file descriptors. You can use it to monitor as many file descriptors as you have. And if you only have one file descriptor, but its value is greater than FD_SETSIZE, epoll works with that too, but select does not.

Randomly, I’ve also recently discovered one slight drawback to epoll as compared to select or poll. While none of these three APIs supports normal files (ie, files on a file system), select and poll present this lack of support as reporting such descriptors as always readable and always writeable. This makes them unsuitable for any meaningful kind of non-blocking filesystem I/O, a program which uses select or poll and happens to encounter a file descriptor from the filesystem will at least continue to operate (or if it fails, it won’t be because of select or poll), albeit it perhaps not with the best performance.

On the other hand, epoll will fail fast with an error (EPERM, apparently) when asked to monitor such a file descriptor. Strictly speaking, this is hardly incorrect. It’s merely signalling its lack of support in an explicit way. Normally I would applaud explicit failure conditions, but this one is undocumented (as far as I can tell) and results in a completely broken application, rather than one which merely operates with potentially degraded performance.

In practice, the only place I’ve seen this come up is when interacting with stdio. A user might redirect stdin or stdout from/to a normal file. Whereas previously stdin and stdout would have been a pipe — supported by epoll just fine — it then becomes a normal file and epoll fails loudly, breaking the application.

posted @ 2016-10-25 10:31  众里寻,阑珊处  阅读(921)  评论(0编辑  收藏  举报
返回顶部