`
阿尔萨斯
  • 浏览: 4169163 次
社区版块
存档分类
最新评论

完成端口之性能优化(2)

 
阅读更多
<iframe align="center" marginwidth="0" marginheight="0" src="http://www.zealware.com/csdnblog.html" frameborder="0" width="728" scrolling="no" height="90"></iframe>
本文作者:sodme 本文出处:http://blog.csdn.net/sodme
版权声明:本文可以不经作者同意任意转载,但转载时烦请保留文章开始前两行的版权、作者及出处信息。

  前面有朋友对本系列文章的题目提出质疑,说:这恐怕不能算是性能优化吧?我要指出的是,本系列文章中提到的优化并不仅仅是某段具体的代码优化,当然这种东西肯定会有,但优化绝不仅仅是这些方面,我这里提到的优化还包括更多的关于模型架构方面的考量。

  上次我提到,在模型里,引入“池”的概念可以有效改善服务器效率。对于完成端口来说,它处理的是成千上万个的客户端连接。在单一客户端连接的情况下,偶尔的多余操作可能并没有给你的系统带来什么不良影响,但这在形如使用完成端口构建的高性能服务器上是绝对应该避免的,不然,你会发现用了完成端口说不定还没有用其它模型来得高效。另外,需要指出的是,完成端口并不是万能模型,有的地方可以考虑用,而有的地方则完全没必要用,至于完成端口在网游服务器模型里的具体使用,我会在另外的文章里提及。

  “池”的概念的引入,最主要的是想让服务器在运行时,维护一个相对静态的数据存储空间,并在这个相对静态的空间上进行相关操作。但是,尽管我们千方百计在诸如此类的地方引入“池”,还是不可避免地要遇到这样的几个问题:拼包操作时的数据移动,内存数据的拷贝,socket与客户端对象的一一对应和定位等。下面,将会针对这三方面介绍有关的优化细节。

  为讨论的方便,在此引入几个状态常量:
  stAccept:表示处于连接建立状态;
  stRecv:表示处于数据接收状态;
  stSend:表示处于数据发送状态。
  注:本文及后续文章,会简称“GetQueuedCompletionStatus”函数为“Get”函数。

  现在我们要讨论的是当Get函数返回时,处于stRecv状态时的数据包拼装问题。我们知道,TCP是流协议,它的数据包大小并不一定就是我们期望的发送或接收时的逻辑包大小,每次发送或接收的大小到底是多少,是根据网络的实际状况来决定的。一个在逻辑意义上完整的包,可能会被TCP分为两次进行发送,第一次发送前半部,第二次发送后半部,由此便带来了不完整数据包的拼装问题。那么,要实现数据包的拼装,必须要有一个地方,可以把两个半截的包放到一起,然后从首部根据逻辑包里的大小定义字段取出相应长度的逻辑包。“把两个半截的包放到一起”,这个操作,就涉及到了数据拷贝问题。在实际的应用中,有两种拼装方案可供选择:第一种方案,是将新收到的后半部分数据包复制到前半部分数据包的末尾,形成一个连续的数据包空间,在此空间的基础上进行拼装操作;第二种方案,不用把新收到的后半部分数据包复制到前半部分的末尾,而是在现有两个缓冲区的基础上直接进行拼装操作,当从前半部分搜索到截开的位置时,将指针直接指向新包首部,取走一个完整逻辑意义的包。

  不论是哪种形式的拼装,可能都会或早或晚地牵涉到剩余数据的拷贝转移问题。第一种方案的情况下,会执行memcpy将新收到的数据包,复制到前半部分数据包的后面;第二种情况,尽管不会首先执行memcpy执行复制,但当执行了“取走所有完整逻辑包”的操作后,缓冲区里可能会残留一个新的不完整的数据包,此时仍需要执行memcpy操作将剩余的这个不完整的数据包复制到原来的前半部分数据包所在的缓冲区,以跟其后续的不完整数据包完成下一步的拼装操作。两种方案的效率,比较起来,第二种方案执行memcpy时所复制的数据内容可能要小得多,所以,相对来说,第二种方案的效率要高一点。

  当然,如果只就数据包的拼装问题而言,我们也完全可以避免数据拷贝操作,方法就是:使用环形缓冲区。环形缓冲区的实现还是比较简单的,具体的代码我这里不会贴出,只介绍它的基本思想。学过数据结构的人都会知道一种叫作“环形队列”的东西(不知道的,请使用GOOGLE搜索),我们这里所说的环形缓冲区正是具体这种特征的接收缓冲区。在服务器的接收事件里,当我们处理完了一次从缓冲区里取走所有完整逻辑包的操作后,可能会在缓冲区里遗留下来新的不完整包。使用了环形缓冲区后,就可以不将数据重新复制到缓冲区首部以等待后续数据的拼装,可以根据记录下的队列首部和队列尾部指针进行下一次的拼包操作。环形缓冲区,在IOCP的处理中,甚至在其它需要高效率处理数据收发的网络模型的接收事件处理中,是一种应该被广泛采用的优化方案。

  memcpy函数的优化,在google上可以搜索到相关主题,用的比较多的优化函数是fastmemcpy,本处给出有关memcpy函数优化的两个连接地址:
http://www.blogcn.com/user8/flier_lu/blog/1577430.html
http://www.blogcn.com/user8/flier_lu/blog/1577440.html
请有兴趣的朋友认真阅读一下这两篇文章。优化的核心思想是:根据系统硬件体系架构,来确定最优的数据拷贝方案。根据以上给出的两个连接地址,memcpy会得到较为明显的优化效果。

  对于网络层来说,每个连接到服务器的客户端唯一标识就是它的socket值,但是,很多情况下,我们需要一个所谓的客户端对象与这个socket能够一一对应,即:以socket值来确定唯一的客户端对象与它对应。于是,我们很自然地会想到使用STL里的map完成这种映射,在实际的使用时,会通过map的查找功能根据socket值取出相应的客户端对象。这样的作法,是较为普遍的作法。但是,尽管map对它的查找算法进行了相应的优化,这个查找也还是要花费一定时间的。如果我们仅仅是要在IOCP的模型里通过GET函数返回时,确定当前返回的socket所代表的那个客户端对象,我们完全可以对投递的overlapped扩展结构进行相应的设置来通过GET函数返回的overlapped扩展结构来直接定位这个客户端对象。

  我的overlapped结构是这样的:
  struct Per_IO_Data{
  OVERLAPPED ov;
  .....
  CIOCPClient* iocpClient;
  .....
  }
  大家可以看到,在我的扩展overlapped结构中,我引入了一个客户端对象指针:iocpClient,每次在投递一个WSASend或WSARecv请求时,都会顺带着这个客户端对象指针。这样,当WSASend或WSARecv操作完成时,就可以通过GET函数执行后返回的Per_IO_Data结构取得这个客户端对象指针,从而就省去了根据socket值进行map查找的步骤。在持续的数据收发下,如果在GET函数里频繁地进行map查找,势必会对性能有较大的影响,而通过传递客户端指针到扩展overlapped结构中实现客户端对象的直接定位则大大节省了查找的时间开销,无疑在性能优化方面又作出了一个重大改进。

  <未完待续>




分享到:
评论

相关推荐

    IOCP完成端口之性能优化

    文档:完成端口之性能优化,别人的帖子,整理了一下,有用的下

    Delphi高性能完成端口模型IOCP

    本例程可以作为初学者的学习之用,亦可以作为大型服务程序的通讯模块。其处理速度可以说,优化到了极点。如果理解了本例程的精髓,加上一个高效的通讯协议,你完全可以用它来构建一个高性能的通讯服务器。

    高性能IOCP完成端口模型

    网上找的IOCP完成端口代码,测试可以实现512Byte 60000包/秒,CPU 10%,单线程,性能已经很好,对代码进行了X64修改,已全面支持X64,准备进一步优化。

    高性能的socket通讯服务器(完成端口模型--IOCP)

    本例程可以作为初学者的学习之用,亦可以作为大型服务程序的通讯模块。其处理速度可以说,优化到了极点。如果理解了本例程的精髓,加上一个高效的通讯协议,你完全可以用它来构建一个高性能的通讯服务器。

    SQLServer安全及性能优化

    SQLServer安全及性能优化 修补漏洞 安装程序补丁修补漏洞 随时关注微软官方网站补丁升级 关闭不必要的端口 关闭联必要的服务 数据库引擎 SQL Server Analysis Services SQL Server Reporting Services SQL ...

    什么是VLAN

     综上,当一个交换机上的所有端口中有至少一个端口属于不同网段的时候,当路由器的一个物理端口要连接2个或者以上的网段的时候,就是VLAN发挥作用的时候,这就是VLAN的目的。 编辑本段VLAN的优点 广播风暴防范  ...

    rust_d3_geo:正在进行d3-geo的端口生锈。 期望Web应用程序的性能提高10倍

    rust_d3_geo 这是库到RUST库板条箱/程序包的端口。 它处于非常早期的开发阶段。 那只是子模块'rotaions'和'polygon_contains'经历了阶段1。阶段1 早期草稿端口-子...阶段2 API完成。 泛型领域可能有优化。 因此,API仅

    金典WNPM 1.0

    录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设置,只需 鼠标一点即可完成。 1、注意事项:金典WNPM 1.0程序所在路径不能含有汉字和空格。 2、MySQL默认用户名:root,密码为...

    任意数据库类型数据转换系统 OBDB2DB 1.7

    优化了目标数据库为 MySQL 时的数据导入性能 针对 MySQL 加入了连接 MySQL 数据库的端口号设置功能 加入了可以选择导入全部数据表还是导入指定的数据表 修正了控件光标跳转顺序错乱的问题 加入了将设置保存为...

    php、mysql、APMServ三者集成的配置程序APMServ 5.2.6(2)(分两个压缩包)

    &4.0.26、Nginx 0.7.19、Memcached 1.2.4、phpMyAdmin 2.11.9.2、OpenSSL、SQLite、 ...虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设 置,只需鼠标一点即可完成。

    代替iis的最好的软件 IIS代替软件所有语言全面支持

    并拥有跟IIS一样便捷的图形管理界面,同时支持MySQL 5.0 & 4.0两个版本,虚拟主机、虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设置,只需鼠标一点即可完成。

    论文研究-SRAM型FPGA单粒子辐照试验系统技术研究.pdf

    为提高FPGA在辐射环境中的可靠性,深入研究抗辐射加固FPGA单粒子效应评估方法,设计优化单粒子效应评估方案,开发相应的评估系统,提出基于SRAM时序修正的码流存储比较技术和基于SelectMAP端口配置回读技术。...

    APMServ使用说明教程

    &4.0.26、Nginx 0.7.19、Memcached 1.2.4、phpMyAdmin 2.11.9.2、OpenSSL、SQLite、 ...虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设 置,只需鼠标一点即可完成。

    PMServ 5.2.6 下

    并拥有跟IIS一样便捷的图形管理界面,同时支持MySQL 5.0 & 4.0两个版本,虚拟主机、虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设置,只需鼠标一点即可完成。

    APMServ使用说明.doc

    &4.0.26、Nginx 0.7.19、Memcached 1.2.4、phpMyAdmin 2.11.9.2、OpenSSL、SQLite、 ...虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设 置,只需鼠标一点即可完成。

    APMServ5.2.6php集成环境

    &4.0.26、Nginx 0.7.19、Memcached 1.2.4、phpMyAdmin 2.11.9.2、OpenSSL、SQLite、 ...虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设 置,只需鼠标一点即可完成。

    php、mysql、Apache三者集成的配置程序APMServ 5.2.6(1)(分两个压缩包)

    &4.0.26、Nginx 0.7.19、Memcached 1.2.4、phpMyAdmin 2.11.9.2、OpenSSL、SQLite、 ...虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设 置,只需鼠标一点即可完成。

    APMServer5.2.6

    并拥有跟IIS一样便捷的图形管理界面,同时支持MySQL 5.0 & 4.0两个版本,虚拟主机、虚拟目录、端口更改、SMTP、上传大小限制、自动全局变量、SSL证书制作、缓存性能优化等设置,只需鼠标一点即可完成。  1、注意...

    iCaMs 布线管理软件

    性能优化:  优化部分菜单显示顺序及逻辑;  规范并定义一批拓扑图编辑快捷键,提高操作效率;  增加CAD图纸的本地硬盘缓存;  增加CAD图纸的内存缓存:3张; iCaMs 3.0.4.0 升级日志(2011/4) 功能增加: ...

Global site tag (gtag.js) - Google Analytics