之前我遇到2個性能問題,都和SO_SNDBUF設置得太小有關。
但是,寫程序的時候可能並不知道把SO_SNDBUF設多大合適,而且SO_SNDBUF也不宜設得太大,浪費內存啊。
於是,有OS提供了動態調整緩沖大小的功能,這樣應用程序就不用再對SO_SNDBUF調優了。
(接受緩沖SO_RCVBUF也是類似的問題, 不應該小於帶寬和延遲的乘積) 。
On Linux:
Linux從2.4開始支持接收 緩沖 和發送緩沖的動態調整。
http://www.man7.org/linux/man-pages/man7/tcp.7.html
------------------------------------------------------------
tcp_rmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These
parameters are used by TCP to regulate receive buffer sizes.
TCP dynamically adjusts the size of the receive buffer from
the defaults listed below, in the range of these values,
depending on memory available in the system.
...
tcp_wmem (since Linux 2.4)
This is a vector of 3 integers: [min, default, max]. These
parameters are used by TCP to regulate send buffer sizes. TCP
dynamically adjusts the size of the send buffer from the
default values listed below, in the range of these values,
depending on memory available.
------------------------------------------------------------
- [root@node2 ~]# cat /proc/sys/net/ipv4/tcp_rmem
- 4096 87380 4194304
- [root@node2 ~]# cat /proc/sys/net/ipv4/tcp_wmem
- 4096 16384 4194304
On Windows:
Windows上其實有類似的機能,但是Windows的文檔太糟糕了,我廢了不少勁才找到一些旁證。
從Vista開始Windows引入接受窗口的自動調整
http://blogs.msdn.com/b/wndp/archive/2007/07/05/receive-window-auto-tuning-on-vista.aspx
從Win7和Win2008R2開始 Windows 引入送信緩沖的自動調整
https://technet.microsoft.com/zh-cn/subscriptions/ms740642.aspx
------------------------------------------------------------
Updated for Windows 7 and Windows Server 2008 R2
...
Dynamic send buffering for TCP was added on Windows 7 and Windows Server 2008 R2. As a result, the use of the SIO_IDEAL_SEND_BACKLOG_CHANGE and SIO_IDEAL_SEND_BACKLOG_QUERY IOCTLs are needed only in special circumstances. For more information, see SIO_IDEAL_SEND_BACKLOG_QUERY .
------------------------------------------------------------
需要注意的是,如果應用設置了SO_SNDBUF,Dynamic send buffering會失效 。
https://msdn.microsoft.com/en-us/library/windows/desktop/bb736549(v=vs.85).aspx
------------------------------------------------------------
Dynamic send buffering for TCP was added on Windows 7 and Windows Server 2008 R2. By default, dynamic send buffering for TCP is enabled unless an application sets the SO_SNDBUF socket option on the stream socket.
------------------------------------------------------------
我在 MSDN上 沒有找到正式介紹這個功能的頁面(也許就沒有這樣的頁面),所以也不知道它的自動調整是怎么個調法,范圍是多少。而且,通過對Win7和Windows Server 2008 R2的測試我也沒看到 送信緩沖自動 調整的效果,這個效果我只在Windows 2012上看到了。
測試:
下面是我的測試,主要針對 送信緩沖的。
以下是各OS中送信緩沖的缺省值
OS 送信緩沖的缺省值 (通過getsockopt(SO_SNDBUF)獲取)
Window7: 8k
Windows2003: 8k
Windows2008: 8k
Windows8: 64k
Windows2012: 64k
測試方法:
1)機器A( Windows )通過TCP socket向機器B 發送100MB數據 。
2) 機器A 每次send()向socket寫入8K字節。
3) 機器A的程序設置不同的 SO_SNDBUF,查看總送信時間的變化。
測試環境1:
Host A: Windows 2012(x64)
Host B: RHEL6(x64)
Network:1Gbit LAN
Result(execute time):
default(64K), 1.118s(送信緩沖的自動調整生效)
set SO_SNDBUF to 32K, 3.295s
set SO_SNDBUF to 64K, 2.048s
set SO_SNDBUF to 128K, 1.404s
set SO_SNDBUF to 256K, 1.290s
從上面可以看出, Windows 2012中 送信緩沖的 自動調整還是很有效果的。
注)如果使用Windows而不是Linux作為客戶端,效果也是一樣的
測試環境 2:
Host A: Windows 2008 R2(x64)
Host B: RHEL6(x64)
Network:1Gbit LAN
Result(execute time):
default(8K), 7.370s
set SO_SNDBUF to 32K, 4.159s
set SO_SNDBUF to 64K, 2.875s
set SO_SNDBUF to 128K, 1.593s
set SO_SNDBUF to 256K, 1.324s
對 Windows 2008 R2,不知道 送信緩沖的 自動調整 沒有生效( " netsh winsock show autotuning " 是生效了的),還是8K初始值的起點太低,反正性能不如人意。
結論:
較新的OS都支持socket buffer的自動調整,不需要應用程序去調優。但對Windows 2012(和Win8)以前的Windows,為了達到最大網絡吞吐,還是要應用程序操心一下 SO_SNDBUF的設置。