在ipq5000 路由器上,使用iperf3测试路由器到下挂pc的吞吐量。pc跑server, 路由器跑client。
测试发现,udp吞吐量只有400多M. 甚至比tcp还低。
udp没有ack,按理讲是不会比tcp低的(其实也不对,ack是另外一个方向的,所以对于单向吞吐量,ack不占用吞吐量方向的带宽)
/ # taskset 2 iperf3 -c 192.168.3.100 -u -b 1200M -t 4
Connecting to host 192.168.3.100, port 5201
[ 5] local 192.168.3.1 port 55059 connected to 192.168.3.100 port 5201
[ ID] Interval Transfer Bitrate Total Datagrams
[ 5] 0.00-1.00 sec 51.0 MBytes 427 Mbits/sec 36901
[ 5] 1.00-2.00 sec 53.8 MBytes 451 Mbits/sec 38924
[ 5] 2.00-3.00 sec 54.3 MBytes 456 Mbits/sec 39343
[ 5] 3.00-4.00 sec 54.4 MBytes 456 Mbits/sec 39400
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 5] 0.00-4.00 sec 213 MBytes 448 Mbits/sec 0.000 ms 0/154568 (0%) sender
[ 5] 0.00-4.00 sec 213 MBytes 448 Mbits/sec 0.005 ms 0/154568 (0%) receiver
iperf Done.
经过排查发现,有一个-l选项,
-l, --length #[KMG] length of buffer to read or write
(default 128 KB for TCP, dynamic or 1460 for UDP)
抓包显示udp的长度为1460,原来iperf3,每次按1460去发包,对于吞吐量测试来说,一个包就对应一次系统调用。这个开销是很大的。
在cpu不强的路由器上来说,这个开销很大。因此可以修改-l选项。对于udp来说,可以搞成最大接近64k.
第一个udp包有ip头+udp头,负载 1500-20-8=1472. 对于后续分片来说只有ip头,负载 1500-20=1480.
为了使每个帧都是满负载,可以设计udp的长度为 1472+n*1480,n取43,得到65112. 是小于65507的最大值。
这样一次send可以发送接近64k的数据,有内核自己去ip分片,这样可以只要1/44的系统调用次数。
使用65112去跑,可以跑满千兆
/ # taskset 2 iperf3 -c 192.168.3.100 -u -b 1200M -t 4 -l 65112
warning: UDP block size 65112 exceeds TCP MSS 1448, may result in fragmentation / drops
Connecting to host 192.168.3.100, port 5201
[ 5] local 192.168.3.1 port 60789 connected to 192.168.3.100 port 5201
[ ID] Interval Transfer Bitrate Total Datagrams
[ 5] 0.00-1.00 sec 114 MBytes 957 Mbits/sec 1838
[ 5] 1.00-2.00 sec 114 MBytes 955 Mbits/sec 1834
[ 5] 2.00-3.00 sec 115 MBytes 961 Mbits/sec 1845
[ 5] 3.00-4.00 sec 115 MBytes 962 Mbits/sec 1846
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Jitter Lost/Total Datagrams
[ 5] 0.00-4.00 sec 457 MBytes 959 Mbits/sec 0.000 ms 0/7363 (0%) sender
[ 5] 0.00-4.00 sec 457 MBytes 958 Mbits/sec 0.029 ms 0/7362 (0%) receiver
iperf Done.