下午验证一个高流量发包问题时,发现了一个值得记录的问题:socket的收发buffer尺寸是会影响收发包的效率的,高流量通讯时,若socket的收发buffer尺寸过小会一定程度降低收发包效率。
自己先分别获取了一下Windows/Linux系统中默认的收发包尺寸值
在x86 Win7环境里实际程序验证结果为
$ ./sockopt.exe UDP socket options: receive buffer: 0x2000 send buffer: 0x2000 TCP socket options: receive buffer: 0x2000 send buffer: 0x2000
只有8KiB。
在cubieboard2环境(Linux cubieboard2 3.4.79 #1 SMP PREEMPT Fri Dec 19 17:51:20 CST 2014 armv7l GNU/Linux)里程序验证结果为
cubie@cubieboard2:~$ ./sockopt_linux UDP socket options: receive buffer: 0x28000 send buffer: 0x28000 TCP socket options: receive buffer: 0x15554 send buffer: 0x4000
可见在Windows下默认的socket收发buffer尺寸都比较小,后续的结果表明,对应对收发包的效率影响更为明显。实际测试代码如下
1 #include "net/udp_peer.h" 2 #include "util/log.h" 3 4 #include <stdlib.h> 5 #include <string.h> 6 7 static inetaddr_t addr; 8 static char data[64000]; 9 10 static void on_message(udp_peer_t *peer, void *message, unsigned size, void* userdata, const inetaddr_t *peer_addr) 11 { 12 return; 13 } 14 15 static void on_writable(udp_peer_t *peer, void* userdata) 16 { 17 udp_peer_send(peer, data, sizeof(data), &addr); 18 19 return; 20 } 21 22 int main(int argc, char *argv[]) 23 { 24 loop_t *loop; 25 udp_peer_t *peer; 26 27 #ifdef WIN32 28 WSADATA wsa_data; 29 WSAStartup(MAKEWORD(2, 2), &wsa_data); 30 #endif 31 32 log_setlevel(LOG_LEVEL_INFO); 33 34 inetaddr_initbyipport(&addr, argv[1], 1994); 35 36 loop = loop_new(64); 37 peer = udp_peer_new(loop, "0.0.0.0", 1994, on_message, on_writable, NULL); 38 udp_peer_expand_send_buffer(peer, (2*1024*1024)); 39 /* udp_peer_expand_recv_buffer(peer, (2*1024*1024)); */ 40 41 loop_loop(loop); 42 43 udp_peer_destroy(peer); 44 loop_destroy(loop); 45 46 #ifdef WIN32 47 WSACleanup(); 48 #endif 49 50 return 0; 51 }
在cubieboard和Windows系统上互相通过UDP进行快速收发包,通过不同方式调节socket收发包buffer尺寸,并进行流量统计,最终得出的结果分别如下(在Windows上利用NetWorx进行流量统计)
1,保持默认的收发buffer尺寸,进行快速发包,直至将百兆带宽打满,流量图如下
2,仅将两端发包buffer尺寸增加2MiB,同样将百兆带宽打满,流量图如下
3,将两端收发包都增加2MiB,将百兆带宽打满,流量图下
可见将socket的发包buffer增大之后,在Windows下发包流量有明显的提升(峰值增加了大概2MiB,约20%)。
自己分析认为这是因为默认情况下Windows下socket发包Buffer较小,发包流量高时,出现发包Buffer满的情况概率较高,而使得后续的sendto()调用失败的概率也对应升高,从而就降低了发包效率,在此处就形成了一个瓶颈,限制了发包流量的进一步升高。而增大socket的发包Buffer之后,此处的限制得到解除,而使得最终的限制就落在网口的最大速率带宽上。
~~ end ~~