在《朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较》一文中,我们分析了各种模型在处理短连接时的能力。本文我们将讨论处理长连接时各个模型的性能。(转载请指明出于breaksoftware的csdn博客)

我们可以想象下场景,如果我们使用朴素模型来处理长连接,则需要引入多线程来处理:主线程接收接入的Socket,子线程处理一个个Socket的读写。因为长连接需要客户端和服务器之间维系一段时间,所以服务器子线程要一直同步等待socket的改变。如果socket长时间没有变化,那么这个子线程就将长期处于闲置状态,这无疑是对资源的一种浪费。然而此时Select、Poll和Epoll模型就能很好的解决这个问题,因为它是异步事件通知模式,所以不需要大量的线程同步等待,可以很好的利用线程资源。

因为我不想引入多线程协助处理,而朴素模型在处理长连接的情况下需要多线程协助,所以我没有将朴素模型列入之后的对长连接支持的改造。还有我也不打算对Select模型代码进行改造,因为我们之前已经分析过,Select模型只能处理一定数量的长连接,所以在高并发的场景下,它也没法使用。于是我们需要改造的是Poll和Epoll模型的代码,其实修改非常简单,我们只要将之前写完回包操作之后的关闭连接给去掉即可。

下一步,我们要对客户端进行改造。为了让客户端足够高效的利用线程资源,我们将客户端也改成Epoll模型。

void* send_data(void* arg) {int wait_time;int epfd, nfds;int client_sock;struct epoll_event ev, events[SOCKET_LIST_COUNT];int in_events, out_events;int index;wait_time = *(int*)arg;in_events = EPOLLIN | EPOLLET;out_events = EPOLLOUT | EPOLLET;epfd = epoll_create1(0);for (index = 0; index < 100; index++) {client_sock = make_client_socket();connect_server(client_sock);set_nonblock(client_sock);request_add(1);ev.data.fd = client_sock;ev.events = in_events;epoll_ctl(epfd, EPOLL_CTL_ADD, client_sock, &ev);client_write(client_sock);ev.events = in_events;epoll_ctl(epfd, EPOLL_CTL_MOD, client_sock, &ev);}   while (1) {nfds = epoll_wait(epfd, events, sizeof(events), 500);usleep(wait_time);for (index = 0; index < nfds; ++index) {int fd = events[index].data.fd;if (events[index].events & EPOLLIN) {if (0 != client_read(fd)) {close(fd);epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL);}else {events[index].events = out_events;epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &events[index]);}}else if (events[index].events & EPOLLOUT) {client_write(fd);events[index].events = in_events;epoll_ctl(epfd, EPOLL_CTL_MOD, fd, &events[index]);}}}close(epfd);
}

我们只对线程函数进行修改。让一个线程新建100个socket去连接服务器,并使用Epoll模型去管理这些socket。

由于我的环境默认只能同时处理1024个连接,所以我使用ulimit -n 3000指令修改了该值,以让我们服务器可以同时处理3000个连接(实际上不到3000个,因为系统还要占用几个)。

最后在3个终端中使用./epoll_client 10 10指令启动客户端,让客户端启动30个线程,共新建3000个长连接。这3000个长连接每隔10微秒向服务器发送和接收一次数据。我们看下Poll模型的稳定时的表现

平均每秒处理27222次“读和写”操作。我们再看下EPoll模型的表现

平均每秒处理18876次“读和写”操作。

我们非常惊讶的发现Epoll模型竟然比Poll模型差!我们使用varlgrind对两种模型进行分析

Poll模型的main函数自身耗时占比仅为12.11%。其主要是读写操作的占用。而其执行循环的次数是 10 113 131次,有效循环是8 374 693次,有效率是82.2%。这个比例还是不错的。

我们再看Epoll模型的统计结果

Epoll模型的main函数自身占用26.56%,这个比例是Poll模型的两倍。其中循环次数和有效循环次数一致,故有效率是100%。

通过上面的对比,我们可以推定就是main函数自身的耗时影响了Epoll模型的效率。

和《朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较》中对Poll和Epoll模型的性能统计分析,我们发现Poll模型的main函数自身耗时占比有明显的变化,前文是46.93%,本文是12.11%。而Epoll模型的main函数自身耗时占比则比较稳定,前文是25.7%,本文是26.56%。

我们再看下CPU和内存的情况

可以发现当前测试环境下两个模型的CPU和内存占用情况是相差不大的。

经过以上分析,我们可以发现在处理长连接时,如果同时连接数量不是很大,且长连接通信频繁时,Poll模型的效率是比Epoll高的。

那么什么时候Epoll效率最高呢?对比Poll和Epoll模型,我们发现Poll模型中有效循环的比例会随着连接数量上涨、通信频度下降而下降。于是我们模拟大量长连接,通信频度不高的场景。

为了能支持高并发,我们需要对我们的系统设置进行一些修改。我的测试环境是Ubuntu Server 14,网上有一篇博文《Ubuntu 12 ulimit 系统最大打开文件个数 设置》,我按此博文介绍将我的环境下的最大连接数改成了40960。这一步非常必要。
        我们使用,/epoll_client 200 1000000指令启动20个线程,供建立20000个连接,各个连接每一秒钟发送一次请求。

我们看下Poll模型的表现

Poll模型平均每秒完成6665次“读和写”操作,且CPU占用率高达65%。

再看下Epoll模型的表现

Epoll模型平均每秒完成6871次“读和写”操作,而CPU占用率只有8.6%。

上述现象说明在大量长连接、不频繁通信的情况下,Epoll模型比Poll模型在CPU消耗上要优秀非常多。

同样我们使用varlgrind分析这种场景下Poll模型和Epoll模型的耗时情况

首先看Poll模型

Poll模型的main函数自身耗时占了64.65%。总循环次数445 973 878,有效循环次数2 135 891,有效率0.48%。

再看看Epoll模型的统计结果

Epolll模型的main函数自身耗时还是稳定在26.57%。总循环次数和有效循环次数一致,故有效率100%。

网上还有很多关于Poll模型和Epoll模型在内核源码级别的对比,并指出Epoll模型的源码是多么的高效。但是使用varlgrind工具测试发现,其主要的性能差距是在无效循环的比例上。而内核源码导致的性能进步却没有明显体现。我们以strlen函数为参考进行对比就可以发现上述观点(可以认为不同程序里对相同内容空间进行strlen操作耗时是一样)。

Poll模型的strlen函数和poll函数的耗时占比是1.21:0.01=121。而Epoll模型中则是9.38:(2.36+0.23)=3.63。

经过这一系列博文的分析,我们可以大致掌握朴素、Select、Poll和Epoll模型的编程方法,同时也对不同场景下选择什么模型有了一定的认识。

最后附上代码链接:http://pan.baidu.com/s/1bTP7MQ 密码:0mc9

朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll、Epoll模型处理长连接性能比较相关推荐

  1. 朴素、Select、Poll和Epoll网络编程模型实现和分析——模型比较

    经过之前四篇博文的介绍,可以大致清楚各种模型的编程步骤.现在我们来回顾下各种模型(转载请指明出于breaksoftware的csdn博客) 模型编程步骤对比 <朴素.Select.Poll和Ep ...

  2. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Epoll模型

    在阅读完<朴素.Select.Poll和Epoll网络编程模型实现和分析--Select模型>和<朴素.Select.Poll和Epoll网络编程模型实现和分析--Poll模型> ...

  3. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Poll模型

    在<朴素.Select.Poll和Epoll网络编程模型实现和分析--Select模型>中,我们分析了它只能支持1024个连接同时处理的原因.但是在有些需要同时处理更多连接的情况下,102 ...

  4. 朴素、Select、Poll和Epoll网络编程模型实现和分析——Select模型

    在<朴素.Select.Poll和Epoll网络编程模型实现和分析--朴素模型>中我们分析了朴素模型的一个缺陷--一次只能处理一个连接.本文介绍的Select模型则可以解决这个问题.(转载 ...

  5. Linux网络编程——tcp并发服务器(poll实现)

    https://blog.csdn.net/lianghe_work/article/details/46535859 想详细彻底地了解poll或看懂下面的代码请参考<Linux网络编程--I/ ...

  6. 基于linux epoll网络编程细节处理丨epoll原理剖析

    epoll原理剖析以及三握四挥的处理 1. epoll原理详解 2. 连接的创建与断开 3. epoll如何连接细节问题 视频讲解如下,点击观看: 基于linux epoll网络编程细节处理丨epol ...

  7. 朴素、Select、Poll和Epoll网络编程模型实现和分析——朴素模型

    做Linux网络开发,一般绕不开标题中几种网络编程模型.网上已有很多写的不错的分析文章,它们的基本论点是差不多的.但是我觉得他们讲的还不够详细,在一些关键论点上缺乏数据支持.所以我决定好好研究这几个模 ...

  8. 【Linux网络编程部分----多进程高并发poll模型】

    目录 前言 背景 分析 编写步骤 服务器: 客户端: 服务器端代码 附:文件操作部分 附:目录操作部分 客户端代码 全部代码 头文件部分 服务器全部代码 客户端所有代码 总结: 前言 本文采用  Vi ...

  9. 【Linux网络编程学习】I/O多路复用——epoll

    此为牛客Linux C++课程和黑马Linux系统编程笔记. 1. 关于epoll epoll是Linux下多路复用IO接口select/poll的增强版本,它能显著提高程序在大量并发连接中只有少量活 ...

最新文章

  1. 程序员4月书讯:Angular来了!
  2. Powershell管理系列(二十五)PowerShell操作之获取AD账号及邮箱信息
  3. MYSQL [ERROR] InnoDB: Unable to lock ./ibdata1 error: 11
  4. 遍历同辈节电的方法_JQuery遍历DOM节点的方法
  5. linux命令学习-4-lsof
  6. 数据源管理 | 动态权限校验,表结构和数据迁移流程
  7. 人魔比妖都恶的时代...
  8. shareSDK 提示#warning:尚未配置[新浪微博]URL Scheme:sinaweibosso.或wb
  9. PYTHON解析XML的多种方式效率对比实测
  10. sql azure 语法_在Azure Data Studio中学习用于SQL Notebook的Markdown语言
  11. PaddlePaddle迁移学习做图像分类,数十种高精度模型任意切换
  12. oracle如何查不满16岁,如何在Oracle数据库中使用SQL查询获取基于年龄组的人数?...
  13. 教职工信息管理系统(C++)
  14. ALSA 中 hw 和 plughw 的区别
  15. python 利用递归算法来完成计算乘阶、斐波那契数列、汉诺塔
  16. 泰拉瑞亚服务器一直显示什么,《泰拉瑞亚》Steam联机总是掉?教你一个稳定联机方法...
  17. 打印俄文字母表java,?俄语字母表、俄文键盘、傻瓜式读音法、书写法大全【一起学俄语】...
  18. 二维数组(矩阵)顺时针旋转90°
  19. MTK 平台获取IMSI号码 以及如何截获系统中的各种消息
  20. android sdl 插件,在Eclipse中配置SDL2.0 for Android

热门文章

  1. Python,OpenCV基于支持向量机SVM的手写数字OCR
  2. C++:随笔6---new\delete\虚方法\抽象方法
  3. OpenCV 错误:无法打开摄像头(打开摄像头卡机)
  4. c+语言+null,C/C++语言中NULL、'\0’和0的区别
  5. win10 error LNK1112: 模块计算机类型“X86”与目标计算机类型“x64”冲突
  6. c语言resource files的作用,c – resource.h中的宏用于什么?
  7. cout 数组_C语言学习笔记(十)二维数组内存预设
  8. Qt创建多线程的步骤
  9. C++ mutable
  10. Vue引入百度地图,如何去掉左下角的版权logo百度等信息?