从 epoll 和 select 的应用场景来更好的了解他们
区别
· | select | epoll |
---|---|---|
实现机制 | 轮询+内存拷贝+集合 | callback+红黑树+mmap+就绪链表 |
主要消耗 | 内存拷贝和大量的轮询 | callback函数 |
最大监测FD数 | 32位系统1024 | nolimit |
兼容性、跨平台性 | POSIX标准 | Linux特有 |
FD增加的影响 | 性能线性下降 | 几乎无影响 |
消息传递方式 | 内存拷贝 | 内存映射 |
表格取自 基于表格形式的select,poll,epoll对比-IO多路复用函数的应用场景
应用场景
从上面的比较可以总结:
select 主要的消耗在于重复的内存拷贝和大量的轮询操作上
epoll 主要的消耗是向内核注册的回调函数上面,文件描述符十分活跃的时候,CPU需要不断的切换上下文,将活跃的FD挂载在链表上,由于有链表的存在使得epoll和poll都可以突破1024
在一开始学习的时候,以为在客户端连接的情况下epoll 都是最好的选择,其实并不然。
当文件描述符在1024以内的时候,select所带来的开支并不会总是epoll 小。
为什么呢?
假设如下场景: 当连接数在1024的时候,这1024条连接全部都是活跃的,时刻都有请求到来,这时候如果使用的是EPOLL,由于EPOLL是事件驱动的,虽然相比于SELECT 避免了FD集合拷贝和轮询的开销,但是频繁的回调函数切换比前者开销更大,同时还需要将活跃的FD插入到链表并将链表拷贝到用户态中,更影响效率。
反观select ,每次拷贝的文件描述符集合大小都是固定的,且轮询操作并不需要涉及到函数切换,在FD活跃的情况下远比EPOLL效率高。
由于限制select效率的最大问题是两次内存拷贝(从用户态到内核态,从内核态到用户态),由于活跃文件描述符过多,EPOLL优势并不明显,相反事件驱动所带来的消耗远比减少一次内存拷贝要来的多。(EPOLL的内存拷贝发生在将就绪链表中的socket拷贝到用户态)
All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Comment