下午驗證一個高流量發包問題時,發現了一個值得記錄的問題: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 ~~