socket buffer size对带宽的影响:iperf 测试结果
在刀片2的 cmm02node06--->cmm02node01 两个结点上,将包长固定在2KB, 用-w选项改变socket buffer size大小,用iperf软件测试两个节点之间的tcp传输带宽,观察随着socket buffer size的变化,传输带宽的变化情况:
1. 只改变发送端的socket buffer size;
2. 只改变接收端的socket buffer size;
3. 同时改变发送端和接收端的socket buffer size.
在不改变发送和接收缓冲区的大小时:
发送端默认的发送缓冲区大小为19.3KB
接收端默认的接收缓冲区大小为85.3 KB
通过-w win 设置缓冲区大小时,若设置成功,缓冲区大小将被设置为(2*win)Byte; 若设置失败,则缓冲区大小不确定。通过不断增大win值,测得,cmm02node01和cmm02node06的缓冲区大小最大为1GB,继续增大win值时,设置的缓冲区大小反而变小了。证明1GB是这两个服务器的发送缓冲区和接收缓冲区的上限。《unix 网络编程卷一:P164》
当 win 为 1KB 时,应将发送缓冲区大小设置为2KB,发现实际上却被设置为2.23KB. (why?不知道)
1. 只改变发送端的socket buffer size时,接收端的缓冲区大小为85.3KB。
在 发送缓冲区 <1MB 时, 随着发送缓冲区的增加,带宽逐渐缓慢增加;
在发送缓冲区 > 1MB 后,带宽较快的变大。
win 值 为 1GB 时, 发送缓冲区被设置为 2KB, 带宽减小到 219 Mb/s。
下面描述了某个应用程序写数据到一个TCP套接字中时发生的步骤。《unix 网络编程卷一:P48》
每个TCP套接字有一个发送缓冲区,我们可以用SO_SNDBUF套接字选项来更改该缓冲区的大小。当某个应用进程调用write时,内核从该应用进程的缓冲区中复制所有数据到所写套接字的发送缓冲区。如果该套接字的发送缓冲区容不下该应用进程的所有数据(或是应用进程的缓冲区大于套接字的发送缓冲区,或是套接字的发送缓冲区中已有其它数据),该应用进程将被投入睡眠。这里假设该应用进程是阻塞的,它是通常的默认设置。内核将不从write系统调用返回,直到应用进程缓冲区中的所有数据都复制到套接字发送缓冲区。因此,从写一个TCP套接字的write调用成功返回仅仅表示我们可以重新使用原来的应用进程缓冲区,并不表明对端的TCP或应用进程已接收到数据。
这一端的TCP提取套接字发送缓冲区中的数据并把它发送给对端TCP, 其过程基于TCP数据传送的所有规则(TCPv1的第19章和第20章,有待详细阅读)。对端TCP必须确认收到的数据,伴随来自对端的ACK的不断到达,本端TCP至此才能从套接字发送缓冲区中丢弃已确认的数据。TCP必须为已发送的数据保留一个副本,直到它被对端确认为止。
本端TCP以MSS大小的或更小的块把数据传递给IP, 同时给每个数据块安上一个TCP首部以构成TCP分节,其中MSS或是由对端通告的值,或是536(若对端未发送一个MSS选项)。(536是IPv4最小重组缓冲区字节数576减去IPv4首部字节数20和TCP首部字节数20的结果。)IP给每个TCP分节安上一个IP首部以构成IP数据报,并按照其目的IP地址查找路由表项以确定外出接口,然后把数据报传递给相应的数据链路。 IP可能在把数据报传递给数据链路之前将其分片,不过我们已经谈到MSS选项的目的之一就是试图避免分片,较新的实现还使用了路径MTU发现功能(之前的测试表明,刀片2上支持路径MTU发现功能)。每个数据链路都有一个输出队列,如果该队列已满,那么新到的分组将被丢弃,并沿协议栈向上返回一个错误:从数据链路到IP, 再从IP到TCP。TCP将注意到这个错误,并在以后的某个时刻重传相应的分节。应用程序并不知道这种暂时的情况。
2. 只改变接收端的socket buffer size时, 发送端的缓冲区大小为19.3KB。
随着接收端缓冲区大小的增加,带宽先增加,后降低;在256KB时,达到最大值。在接收缓冲区大于256KB后,带宽的趋势是突然降低,并随后保持在较低水平。
接收缓冲区被TCP用来保存接收到的数据,直到由应用程序来读取。对于TCP来说,套接字接收缓冲区中可用空间的大小限定了TCP通告对端的窗口大小。TCP套接字接收缓冲区不可能溢出,因为不允许对端发出超过本端所通告窗口大小的数据。这就是TCP的流量控制,如果对端无视窗口大小而发出了超过该窗口大小的数据,本端TCP将丢弃它们。
3. 同时改变发送端和接收端的socket buffer size时。
当缓冲区大小 < 1MB 时, 随着缓冲区的增加,带宽缓慢增加,逐渐平稳在一个较低值;
当缓冲区大小 > 1MB 后,随着缓冲区的增加,带宽先大幅度增加后降低并保持在8~9Gb/s。
比较三种情况下的带宽曲线:
可以从上图得出的结论是,在现有的网络和硬件环境下, 要得到较大的带宽,有3种情况:
1. 只设置接收端缓冲区大小是达不到最大带宽的,但是接收缓冲区为256KB是一个较好的设置值,可以固定接收端为256KB, 继续测试出一组最佳匹配值。
2. 设置较大的发送端和接收端窗口,最佳匹配是[8MB, 8MB], 也可在最佳匹配值左右进行选择。
3. 只设置大的发送端的缓冲区大小,>=16MB, 此时的带宽能达到12~14Gb/s
1. 固定接收端缓冲区为256KB
将接收端的缓冲区大小固定为256KB,改变发送端的缓冲区大小,测试一组带宽值以找到发送端缓冲区最佳匹配值。由于发送端的发送缓冲区大小设置应大于带宽延迟乘积(见《unix 网络编程卷一:P164》),通过ping命令得到cmm02node01与cmm02node06之间的RTT在0.1ms与0.2ms之间,保守估计按照0.2ms计算,对40Gb以太网数据链路,带宽延迟乘积=40Gb/(8bits/Byte)*0.2ms/(1000ms/s)=1MB, 也就是说,在发送缓冲区小于1MB时,两个通信结点之间的管道容量不会被填满,带宽将不会达到期望值。因此,在下面的测试曲线中,发送缓冲区最小设置为1MB, 最大设置为1GB。
由下图可以看出,固定接收端缓冲区大小为256KB时, 得到的最佳匹配值为[256KB,>= 16MB], 此时的带宽能达到12Gb/s左右。
2. 固定接收端缓冲区大小为8MB
为了验证第二组最佳匹配值,将接收端的缓冲区大小设置为8MB, 发送端缓冲区大小区间为 [1MB, 1GB] , 进行了一组测试。测试结果如下: 从图中可以看出第二组最佳匹配值为[8MB, >=8MB], 此时的带宽能达到12Gb/s左右。
综上所述:
在寻找ROS的socket 缓冲区的最佳匹配值时,有三种匹配值可供选择:
1. 只设置发送缓冲区 >= 16MB
2. [256KB,>= 16MB]
3. [8MB, >=8MB]
结论就是,发送缓冲区必须要大, 接收缓冲区在 默认85.3,256KB左右 ,8MB 及以上这三个区间择优选择,最大的带宽应该在12Gb/s左右。