在高并发服务器中,轮询I/O是最耗时间的操作之一,select 和 epoll 的性能谁的性能更高
select的调用复杂度是线性的,即O(n)
举个例子,一个保姆照看一群孩子,如果把孩子是否需要尿尿比作网络IO事件,select的作用就好比这个保姆挨个询问每个孩子:你要尿尿吗?如果孩子回答是,保姆则把孩子拎出来放到另外一个地方。当所有孩子询问完之后,保姆领着这些要尿尿的孩子去上厕所(处理网络IO事件)。 还是以保姆照看一群孩子为例
select本质上是通过设置或检查存放fd标志位的数据结构进行下一步处理。 这带来缺点:
- 单个进程可监视的fd数量被限制,即能监听端口的数量有限 单个进程所能打开的最大连接数有
FD_SETSIZE
宏定义,其大小是32个整数的大小(在32位的机器上,大小就是3232,同理64位机器上FD_SETSIZE为3264),当然我们可以对进行修改,然后重新编译内核,但是性能可能会受到影响,这需要进一步的测试 一般该数和系统内存关系很大,具体数目可以cat /proc/sys/fs/file-max
察看。32位机默认1024个,64位默认2048。

- 对socket是线性扫描,即轮询,效率较低: 仅知道有I/O事件发生,却不知是哪几个流,只会无差异轮询所有流,找出能读数据或写数据的流进行操作。同时处理的流越多,无差别轮询时间越长 - O(n)。
当socket较多时,每次select都要通过遍历FD_SETSIZE
个socket,不管是否活跃,这会浪费很多CPU时间。如果能给 socket 注册某个回调函数,当他们活跃时,自动完成相关操作,即可避免轮询,这就是epoll与kqueue。
1.1 调用过程

epoll机制
保姆不再需要挨个的询问每个孩子是否需要尿尿。取而代之的是,每个孩子如果自己需要尿尿的时候,自己主动的站到事先约定好的地方,而保姆的职责就是查看事先约定好的地方是否有孩子。如果有小孩,则领着孩子去上厕所(网络事件处理)。
select单个进程可监视的fd数量受到限制 epoll和select都可以实现同时监听多个I/O事件的状态。
select 基于轮训机制
epoll基于操作系统支持的I/O通知机制 epoll支持水平触发和边沿触发两种模式
No comments:
Post a Comment