select poll epoll 区别
所属分类 architecture
浏览量 1508
IO多路复用
监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),通知程序进行相应的读写操作。
select 时间复杂度O(n)
仅仅知道有IO事件发生,但不知道是哪几个,只能无差别轮询所有通道
poll 时间复杂度O(n)
本质上和select没有区别,将用户传入的数组拷贝到内核空间,然后查询每个fd对应的设备状态,
但是没有最大连接数限制,因为基于链表存储
epoll 时间复杂度O(1)
可以理解为event poll , epoll会把哪个流发生了怎样的IO事件发出通知
事件驱动
select,poll,epoll本质上都是同步IO,在读写事件就绪后需要自己负责进行读写,也就是说这个读写过程是阻塞的,
而异步IO则无需自己负责进行读写,异步IO的实现会负责把数据从内核拷贝到用户空间。
IO模式 Proactor与Reactor
select本质上是通过设置或者检查存放fd标志位的数据结构来进行下一步处理。 缺点
1 单个进程可监视的fd数量有限制
/proc/sys/fs/file-max 32位机默认1024 64位机默认2048
2 对socket进行扫描时是线性扫描,即采用轮询的方法,效率较低:
当套接字比较多的时候,全部遍历一遍 ,会浪费很多CPU时间
3 需要维护一个用来存放大量fd的数据结构,这样会使得用户空间和内核空间在传递该结构时复制开销大
poll 水平触发 ,如果报告了fd后,没有被处理,那么下次poll时会再次报告该fd
epoll有EPOLLLT和EPOLLET两种触发模式
LT 水平触发
ET 边缘触发
epoll优点
1 没有最大并发连接限制,能打开的FD上限远大于1024(1G内存能监听约10万个端口)
2 效率提升,非轮询方式,不会随着FD数目的增加导致效率下降。只有活跃可用的FD才会调用callback函数
3 内存拷贝,利用mmap()文件映射内存加速与内核空间的消息传递,使用mmap减少复制开销
消息传递方式
select:内核需要将消息传递到用户空间,需要内核的拷贝动作;
poll:同上;
epoll:通过内核和用户空间共享一块内存来实现,性能较高;
文件句柄剧增后带来的IO效率问题
select:因为每次调用都会对连接进行线性遍历,所以随着FD剧增后会造成遍历速度的“线性下降”的性能问题;
poll:同上;
epoll:由于epoll是根据每个FD上的callable函数来实现的,只有活跃的socket才会主动调用callback,所以在活跃socket较少的情况下,使用epoll不会对性能产生线性下降的问题,如果所有socket都很活跃的情况下,可能会有性能问题;
一个进程所能打开的最大连接数
select:
单个进程所能打开的最大连接数,是由FD_SETSIZE宏定义的,其大小是32个整数大小(在32位的机器上,大小是3232,64位机器上FD_SETSIZE=3264),
可以对其进行修改,然后重新编译内核,但是性能无法保证,需要做进一步测试;
poll:本质上与select没什么区别,但是他没有最大连接数限制,他是基于链表来存储的;
epoll:虽然连接数有上线,但是很大,1G内存的机器上可以打开10W左右的连接;
上一篇
下一篇
netty ByteBuf 使用
dubbo实例
IO模式 Proactor与Reactor
netty ByteBuf vs java NIO ByteBuffer
netty高性能之道
PooledByteBufAllocator跟踪调试