• 如何提高完成端口的性能


    背景:

    刚做完了一个关于网络流量测试的工具,用于测试网络系统中的服务器可支持的连接数、通信的收发速度等功能,包括服务器和客户端两个程序,服务器和客户端都使用完成端口技术来实现。在通信速度为1.0Gbps网络中,两台一样配置(CPU为Pentium(R) Dual-Core E5800 @ 3.2GHz,内存4GB,操作系统为Windows Server 2008 R2 Enterprise)的计算机分别跑服务器程序和客户端程序,测得的结果如下:在单向传输数据时,最大连接为16000,此时传输速度为110MB/S左右;在双向传输数据时,最大连接数为7000,此时传输速度为140MB/S左右。用了一个月才完成此程序,碰了很多壁,现在写一下一些经验总结。此文假设读者已经了解完成端口的基本知识,如果读者第一次接触完成端口,可以先看一下这篇文章(http://msdn.microsoft.com/msdnmag/issues/1000/Winsock/)。

    提高完成端口性能的要点:

    一、使用服务器的操作系统:

    我们使用32bit的Windows XP professional SP3系统(硬件配置:CPU为Pentium(R) Dual-Core E2160 @ 1.8GHz,内存2GB)和64bit的Windows Server 2008 R2 Enterprise系统(硬件配置:CPU为Pentium(R) Dual-Core E5800 @ 3.2GHz,内存4GB)进行测试。测试的结果完成不一样,如在单向传输出中,在XP系统下,1000个连接(每个连接传5MB数据)都无法传完(传输过程中有些连接会失败);而在Server 2008系统中,16000个连接(每个连接传5MB数据)却可以正确地传输完。

    在我们测试过程中,两种系统的一些资源分配不同影响了系统的性能,具体有以下几点:

    1.在两种系统中,应用程序能使用的non-paged(中文叫未分页,或非分页)内存的大小不一样。在我们的测试中,XP系统的non-paged内存最大使用量为256MB(有文档说系统non-paged内存的大小为物理内存的1/8,XP系统应该就属于这类系统吧);而在Server 2008中,测试的最大的non-paged内存为2.9GB,为什么说最大呢?因为这一结果出现时,PF使用已经接近4GB了,这时系统可能没有多余的物理内存分配给non-paged内存,你可能会说,不是还有1.1GB吗?其实在这剩余1.1GB内存中,有很大一部分是分配给我们每个连接的收发缓冲区(假设只有单向传输,有16000个连接,我们每个连接的程序收发缓冲区为64KB,差不多就用了1GB),这些收发缓冲区虽然是paged内存,但其经常会被使用到,所以基本上占用了同样大小的物理内存。

    2.另一个不同的地方是两种系统给每条连接可使用的最大non-paged内存不一样,在XP系统下,测得其值是300多KB(其实还测到其另一个值为700多KB,只是在Server 2008系统中没有使用这种测试方法,所以,不用它来比较),而在2008系统下,测得其值是80多KB。

    从上面两点可以看出,XP系统可用的总non-paged内存比较小,而每个连接最大可用的non-paged内存却比较大;而Server 2008系统可用的总non-paged内存比较大,每个连接最大可用的non-paged内存却比较小。所以,Server 2008系统可带的连接当然比XP系统的多很多,不用犹豫了,选服务器的操作系统(我们只测过Windows Server 2008 R2 Enterprise系统,其它服务器操作系统还没测试)就对了。

    二、提高程序的收发速度:

    整个网络通信系统的通信速度至少取决于发送速度,传输速度和接收速度,而且网络的通信速度小于这三个速度中最小的速度。提高了这三个速度中最小的速度,一般也会相应地提高了整个网络的通信速度。

    在通信速度为1.Gbps的网络中,其最大的接收和发送速度大概都为119MB/S(假如不计算TCP报文和IP数据报的首部)。当网络的通信速度远低于这个速度时,则很有可能是的收发速度太慢了。

    而如何提高程序的收发速度呢?我这里有一个测试结果,你看完马上就知道了。测试结果为“在本地测试中,把程序的收发缓冲区从4KB改为128KB,程序的收发速度从6.410MB/S变成了71.428MB/S”。是不是一看完就知道怎么做了?虽然这个是在本地测试的结果,但在网络通信中,也会得到相似的结果。当程序的收发缓冲区变大后,收发同样大小的数据量,其收发次数减少了,减少了CPU等资源的开销,所以,提高程序的收发速度。当然收发缓冲区也不要太大,当收发缓冲区太大,也会增加系统non-paged内存的使用的。

    三、减少不必要的系统资源开销:

    这些系统资源包括内存和CPU。

    内存:关于完成端口的AcceptEx函数,有一个好处,就是可以通过一次调用就完成接受客户端连接请求和接收第一组数据。但是我们并没有使用这个好处,因为我们程序连接上后客户端可能不会发送数据的。所以,我们对AcceptEx和ConnectEx的单IO数据使用最小的缓冲区,则AcceptEx的接收缓冲区的最小值为((sizeof(SOCKADDR_IN)+16)*2),ConnectEx的发送缓冲区可设为0。由于我们程序在测试时连接是高并发的,预投数和连接数都比较多,通过修改这两个缓冲区的大小,大概减少几百MB的内存使用(之前使用与收发的单IO数据一样大小的缓冲区)。

    CPU:关于减少CPU的可能对大多数人不适用。因为我们做的网络通信性能的测试,所以,要记录下每条连接的信息,当其出错时,可以立即查出什么原因,而且这些连接的信息每1秒会更新一次,当有7000个连接时,则更新这一功能就占用了我们机器CPU的50%资源。后来,把更新变成可选功能,则大大提高了整个通信系统的性能。

    四、控制non-paged内存的使用:

    终于到这里了。控制non-paged内存的使用是我目前觉得提高完成端口的性能最重要的技术(可能是因为我还没解决这个问题吧)。在我们的程序中,没有对non-paged内存的使用进行控制。在发送时,如果发送速度大于网络的通信速度,则在发送方就会有数据积压,占用大量的non-paged的内存。当没有non-paged内存可用时,则会返回错误号10055(意思是:由于系统缓冲区空间不足或队列已满,不能执行套接字上的操作)的错误代码,这样很好处理,当出现这样的错误时,就暂停发送就行了。但是,如果是发送和接收同时出现呢?用这种方法就没办法处理了(单向的接收出现积压数据没有进行测试)。

    在我们测试工具的,我们是通过提高程序的收发速度,并且只使用单向传输数据来避免这个问题产生的。因为这样设置可以使数据只积压在发送方,而数据积压在发送方我们的程序可以进行有效地控制。

    关于non-paged内存的使用,对于每条单向连接,主要考虑以下两个地方:1、程序的收发缓冲区,当你投递发送请求时,系统返回997(意思是:重叠 I/O 操作在进行中)的错误代码,则此收发缓冲区会被锁定在non-paged内存中,等待内核对这块内存进行操作;2、系统低层对每条连接分配的non-paged内存缓冲区(也就是我上面XP系统测得的300多KB,Server 2008系统测得的80多KB),这个non-paged内存用于存储我们程序将要发送或将要接收的数据。这两个地方的non-paged内存使用,大概就是一条连接需要的non-paged内存了。至于双向通信的连接,我测的比较少,有可能是简单地相加或更复杂。

    结束语:

    以上只是我这一个月做这个项目一些经验总结。虽然很多结论都有测出一些数据进行论证,但很多地方这些数据并不能充分地得出这一个结论,而且测出的数据也有可能因为环境的不同而不同。所以,一定要带着问号看这篇文章。我也是刚接触完成端口这方面的知识,希望能与大家门交流学习。转载请注明出处,我的博客是http://www.cnblogs.com/shiyixin/

  • 相关阅读:
    ExtJs自学教程(1):从一切API开始
    集成框架 javaweb开发平台ssmy_m(生成代码) java struts2 mybatis spring maven jquery
    hdu2203 KMP水的问题
    Hibernate制图(两)——许多-于─关系映射
    FPGA 异步时钟处理方
    在Magento产品页面的使用jqZoom
    struts2基本介绍
    让你提前知道软件开发(45):第一印象的代码
    struts2 模型分配问题和延迟加载问题
    性能优化(一个)Hibernate 使用缓存(一个、两、查询)提高系统性能
  • 原文地址:https://www.cnblogs.com/shiyixin/p/3430218.html
Copyright © 2020-2023  润新知