源地址:http://sheepxxyz.blog.163.com/blog/static/61116213201022003513530/

  随着2.6内核对epoll的完全支持,网络上很多的文章和示例代码都提供了这样一个信息:使用epoll代替传统的poll能给网络服务应用带来性能上的提升。但大多文章里关于性能提升的原因解释的较少,这里我将试分析一下内核(2.6.21.1)代码中poll与epoll的工作原理,然后再通过一些测试数据来对比具体效果。

POLL:

先说poll,poll或select为大部分Unix/Linux程序员所熟悉,这俩个东西原理类似,性能上也不存在明显差异,但select对所监控的文件描述符数量有限制,所以这里选用poll做说明。
    
       poll是一个系统调用,其内核入口函数为sys_poll,sys_poll几乎不做任何处理直接调用do_sys_poll,do_sys_poll的执行过程可以分为三个部分:

1,将用户传入的pollfd数组拷贝到内核空间,因为拷贝操作和数组长度相关,时间上这是一个O(n)操作,这一步的代码在do_sys_poll中包括从函数开始到调用do_poll前的部分。

2,查询每个文件描述符对应设备的状态,如果该设备尚未就绪,则在该设备的等待队列中加入一项并继续查询下一设备的状态。查询完所有设备后如果没有一个设备就绪,这时则需要挂起当前进程等待,直到设备就绪或者超时,挂起操作是通过调用schedule_timeout执行的。设备就绪后进程被通知继续运行,这时再次遍历所有设备,以查找就绪设备。这一步因为两次遍历所有设备,时间复杂度也是O(n),这里面不包括等待时间。相关代码在do_poll函数中。

3,将获得的数据传送到用户空间并执行释放内存和剥离等待队列等善后工作,向用户空间拷贝数据与剥离等待队列等操作的的时间复杂度同样是O(n),具体代码包括do_sys_poll函数中调用do_poll后到结束的部分。

EPOLL:

接下来分析epoll,与poll/select不同,epoll不再是一个单独的系统调用,而是由epoll_create/epoll_ctl/epoll_wait三个系统调用组成,后面将会看到这样做的好处。

先来看sys_epoll_create(epoll_create对应的内核函数),这个函数主要是做一些准备工作,比如创建数据结构,初始化数据并最终返回一个文件描述符(表示新创建的虚拟epoll文件),这个操作可以认为是一个固定时间的操作。

epoll是做为一个虚拟文件系统来实现的,这样做至少有以下两个好处:

1,可以在内核里维护一些信息,这些信息在多次epoll_wait间是保持的,比如所有受监控的文件描述符。

2, epoll本身也可以被poll/epoll;

具体epoll的虚拟文件系统的实现和性能分析无关,不再赘述。

在sys_epoll_create中还能看到一个细节,就是epoll_create的参数size在现阶段是没有意义的,只要大于零就行。

接着是sys_epoll_ctl(epoll_ctl对应的内核函数),需要明确的是每次调用sys_epoll_ctl只处理一个文件描述符,这里主要描述当op为EPOLL_CTL_ADD时的执行过程,sys_epoll_ctl做一些安全性检查后进入ep_insert,ep_insert里将 ep_poll_callback做为回掉函数加入设备的等待队列(假定这时设备尚未就绪),由于每次poll_ctl只操作一个文件描述符,因此也可以认为这是一个O(1)操作

ep_poll_callback函数很关键,它在所等待的设备就绪后被系统回掉,执行两个操作:

1,将就绪设备加入就绪队列,这一步避免了像poll那样在设备就绪后再次轮询所有设备找就绪者,降低了时间复杂度,由O(n)到O(1);
    
       2,唤醒虚拟的epoll文件;

最后是sys_epoll_wait,这里实际执行操作的是ep_poll函数。该函数等待将进程自身插入虚拟epoll文件的等待队列,直到被唤醒(见上面ep_poll_callback函数描述),最后执行ep_events_transfer将结果拷贝到用户空间。由于只拷贝就绪设备信息,所以这里的拷贝是一个O(1)操作。

还有一个让人关心的问题就是epoll对EPOLLET的处理,即边沿触发的处理,粗略看代码就是把一部分水平触发模式下内核做的工作交给用户来处理,直觉上不会对性能有太大影响,感兴趣的朋友欢迎讨论。

POLL/EPOLL对比:

表面上poll的过程可以看作是由一次epoll_create/若干次epoll_ctl/一次epoll_wait/一次close等系统调用构成,实际上epoll将poll分成若干部分实现的原因正是因为服务器软件中使用poll的特点(比如Web服务器):

1,需要同时poll大量文件描述符;

2,每次poll完成后就绪的文件描述符只占所有被poll的描述符的很少一部分。

3,前后多次poll调用对文件描述符数组(ufds)的修改只是很小;

传统的poll函数相当于每次调用都重起炉灶,从用户空间完整读入ufds,完成后再次完全拷贝到用户空间,另外每次poll都需要对所有设备做至少做一次加入和删除等待队列操作,这些都是低效的原因。

epoll将以上情况都细化考虑,不需要每次都完整读入输出ufds,只需使用epoll_ctl调整其中一小部分,不需要每次epoll_wait都执行一次加入删除等待队列操作,另外改进后的机制使的不必在某个设备就绪后搜索整个设备数组进行查找,这些都能提高效率。另外最明显的一点,从用户的使用来说,使用epoll不必每次都轮询所有返回结果已找出其中的就绪部分,O(n)变O(1),对性能也提高不少。

此外这里还发现一点,是不是将epoll_ctl改成一次可以处理多个fd(像semctl那样)会提高些许性能呢?特别是在假设系统调用比较耗时的基础上。不过关于系统调用的耗时问题还会在以后分析。

POLL/EPOLL测试数据对比:

测试的环境:我写了三段代码来分别模拟服务器,活动的客户端,僵死的客户端,服务器运行于一个自编译的标准2.6.11内核系统上,硬件为 PIII933,两个客户端各自运行在另外的PC上,这两台PC比服务器的硬件性能要好,主要是保证能轻易让服务器满载,三台机器间使用一个100M交换机连接。

服务器接受并poll所有连接,如果有request到达则回复一个response,然后继续poll。

活动的客户端(Active Client)模拟若干并发的活动连接,这些连接不间断的发送请求接受回复。

僵死的客户端(zombie)模拟一些只连接但不发送请求的客户端,其目的只是占用服务器的poll描述符资源。

测试过程:保持10个并发活动连接,不断的调整僵并发连接数,记录在不同比例下使用poll与epoll的性能差别。僵死并发连接数根据比例分别是:0,10,20,40,80,160,320,640,1280,2560,5120,10240。

下图中横轴表示僵死并发连接与活动并发连接之比,纵轴表示完成40000次请求回复所花费的时间,以秒为单位。红色线条表示poll数据,绿色表示 epoll数据。可以看出,poll在所监控的文件描述符数量增加时,其耗时呈线性增长,而epoll则维持了一个平稳的状态,几乎不受描述符个数影响。

在监控的所有客户端都是活动时,poll的效率会略高于epoll(主要在原点附近,即僵死并发连接为0时,图上不易看出来),究竟epoll实现比poll复杂,监控少量描述符并非它的长处。

[转载] select, poll和epoll的区别的更多相关文章

  1. Linux中select poll和epoll的区别

    在Linux Socket服务器短编程时,为了处理大量客户的连接请求,需要使用非阻塞I/O和复用,select.poll和epoll是Linux API提供的I/O复用方式,自从Linux 2.6中加 ...

  2. Linux下select, poll和epoll IO模型的详解

    http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll 介绍 Epoll 可是当前在 Linux 下开发大规模并发网络程序的热 ...

  3. I/O复用中的 select poll 和 epoll

    I/O复用中的 select poll 和 epoll: 这里有一些不错的资料: I/O多路复用技术之select模型: http://blog.csdn.net/nk_test/article/de ...

  4. (转)Linux下select, poll和epoll IO模型的详解

    Linux下select, poll和epoll IO模型的详解 原文:http://blog.csdn.net/tianmohust/article/details/6677985 一).Epoll ...

  5. linux select poll and epoll

    这里以socket文件来阐述它们之间的区别,假设现在服务器端有100 000个连接,即已经创建了100 000个socket. 1 select和poll 在我们的线程中,我们会弄一个死循环,在循环里 ...

  6. 聊聊select, poll 和 epoll

    聊聊select, poll 和 epoll 假设项目上需要实现一个TCP的客户端和服务器从而进行跨机器的数据收发,我们很可能翻阅一些资料,然后写出如下的代码. 服务端 void func(int s ...

  7. Select,poll,epoll复用

    Select,poll,epoll复用 1)select模块以列表的形式接受四个参数,分别是可读对象,可写对象,产生异常的对象,和超时设置.当监控符对象发生变化时,select会返回发生变化的对象列表 ...

  8. select、poll和epoll的区别(转载)

    select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述符,一旦某个描述符就绪(一般是读就绪或者写就绪),能够通知程序进行相应的读写操作.但select ...

  9. select、pselect、poll和epoll的区别

    select.pselect.poll和epoll函数是unix中具有I/O复用的函数.什么是I/O复用?为什么要有I/O复用?以及在什么场合下使用I/O复用?既然都具有I/O复用的功能,那这几个函数 ...

随机推荐

  1. android开发系列之消息机制

    最近接触到一个比较有挑战性的项目,我发现里面使用大量的消息机制,现在这篇博客我想具体分析一下:android里面的消息到底是什么东西,消息机制到底有什么好处呢? 其实说到android消息机制,我们可 ...

  2. SQL-Server数据库学习笔记-表

    1. 表及其属性 表(Table):也称实体,是存储同类型数据的集合. 列(Field):也称字段.域或属性,它构成表的架构,具体表示为一条信息中的一个属性. 行(Row):也称元组(Tuple),存 ...

  3. iOS开发HTTPS实现之信任SSL证书和自签名证书

    iOS开发HTTPS实现之信任SSL证书和自签名证书 转自:http://www.jianshu.com/p/6b9c8bd5005a/comments/5539345 (收录一下供自己学习用的) 字 ...

  4. 微软职位内部推荐-Senior SDE

    微软近期Open的职位: Position: Senior SDE-- Mobile Products Android/iOS/WP Senior Developer Contact Person: ...

  5. WEB 容器、WEB服务和应用服务器的区别与联系

    Web容器:    何为容器?    容器是一种服务调用规范框架,j2ee大量运用了容器和组件技术来构建分层的企业级应用,在J2EE规范中,相应的有Web Container和EJB Containe ...

  6. C#委托详解(2):实现方式大全

    本系列文章将详细探讨C#中的委托,列举其主要的实现方式,并分析其在设计层面和编码层面带来的好处,最后会讨论其安全性和执行效率等. 接上篇(C#委托详解(1):什么是委托)介绍完什么是委托之后,来看看C ...

  7. Netsharp介绍

    1.1     Netsharp是什么 Netsharp定义: Netsharp业务基础平台 = 1.系统框架 + 2.元数据 + 3.平台工具 + 4.基础业务 + 5.二次开发 此五个概念请参考什 ...

  8. 前端之JavaScript第一天学习(2)-JavaScript 使用

    HTML 中的脚本必须位于 <script> 与 </script> 标签之间.脚本可被放置在 HTML 页面的 <body> 和 <head> 部分中 ...

  9. mac下phpstorm左侧的project列表找不到了

    早上开机,发现左侧的project列表没有了,用着不方便,当然了,是可以调出来的. View-Tool Windows-Project,就出来来. 快捷键:command+1. 问题解决.

  10. 重读《Struts In Action》

    Figure   1.1. The Java Servlet API exposes the HTTP client/server protocol to the Java   platform. S ...