1Gb LAN上のiperfを介して2つのUbuntuサーバー(12.04)間でデータを転送します。
iperf -s <-> iperf -c <addr> -n2G
TCP speed = 925 Mbits/sec
iperf -su <-> iperf -uc<addr> -b1G -n2G
UDP speed = 810 Mbits/sec
Jitter = 0.016 ms
Lost = 0 .. 0.01%
UDPはTCPよりもはるかに高速だと思いました。 UbuntuサーバーでUDPがTCPより遅い理由を誰かが説明できますか?
各フレームは、送信時にいくつかのバッファー(アプリケーションバッファー、プロトコルバッファー、ソフトウェアインターフェイスバッファー、ハードウェアインターフェイスバッファー)を通過します。高速データを送信してスタックにストレスをかけ始めると、これらのバッファーがいっぱいになり、データがブロックされるか失われます。また、パフォーマンスに影響を与える可能性のある適時性とポーリングの戦略もあります。たとえば、より大きなバッファを使用してポーリングの頻度を減らすことで、レイテンシを犠牲にしながらパフォーマンスを大幅に向上させることができます。
TCPは高速バルク転送用に最適化されており、UDPはLinuxカーネルの低遅延用に最適化されています。これは、バッファサイズと、データのポーリングおよびハンドオーバーの方法に影響を与えます。これに加えて、TCPのハードウェアへのオフロードが頻繁に発生します。 UDPと比較してTCPの方がかなり優れたパフォーマンスを期待します。
独自の輻輳制御を実装しない限り、UDPを介して高速データを送信することは通常は悪い考えであることに注意してください。 TCPは、輻輳の崩壊からネットワークを保護します。データ量が少ない場合や適時性が高い場合は、UDPを使用してください。
上で述べたように、iperfは設計上それ自体を制限します。 _src/Client.cpp
_では、メソッド
_void Client::Run( void )
_
呼び出し
_ReportPacket( mSettings->reporthdr, reportstruct );
_
各UDPデータグラムを書き込んだ後。
ReportPacket()
はかなり遅く、全体が遅くなります。
Iperf3では、UDPにバースト書き込みが導入されています。バースト書き込みの数は、_-b
_のように_-b 10240M/2000
_コマンドラインパラメーターで指定できます。
それ以外の場合は、_-t UDP_STREAM
_でnetperfを使用できます。
問題はiperf自体の内部にあります。 UDPフローを送信すると、iperfはフロー内のデータグラムごとに内部ブックキーピングを実行します。一方、TCPストリームを送信すると、iperfはストリームごとに1回だけ簿記を行います。私の測定では、iperf-UDPはデータグラムごとの測定を行うのに多くの時間を浪費するため、パフォーマンスが低下します。
本当にTCP vs UDPパフォーマンスを比較したい場合は、独自のテストプログラムを作成する方がよいでしょう。そして、両方の場合で計算量が同じであることを確認してください。