web-dev-qa-db-ja.com

いつTCP_NODELAYを使用し、TCP_CORKを使用する必要がありますか?

両方ともNagleのアルゴリズムを無効にすることを理解しました。

それらのそれぞれを使用すべき/使用すべきでないのはいつですか?

57
user360455

まず第一に、両方ともNagleのアルゴリズムを無効にしません。

Nagleのアルゴリズムは、有線の小さなネットワークパケットの数を減らすためのものです。アルゴリズムは、データが制限(通常はMSS)よりも小さい場合、以前に送信されたパケットのACKを受信するまで待機し、その間にユーザーからデータを蓄積します。次に、蓄積されたデータを送信します。

if [ data > MSS ]
    send(data)
else
    wait until ACK for previously sent data and accumulate data in send buffer (data)
    And after receiving the ACK send(data)

これは、telnetなどのアプリケーションで役立ちます。ただし、ACKを待機すると、ストリーミングデータを送信する際の遅延が増加する場合があります。さらに、受信者が「遅延ACKポリシー」を実装すると、一時的なデッドロック状態が発生します。このような場合、Nagleのアルゴリズムを無効にする方が良いオプションです。

したがって、TCP_NODELAYはNagleのアルゴリズムを無効にするために使用されます。

TCP_CORKは積極的にデータを蓄積します。ソケットでTCP_CORKが有効になっている場合、バッファが一定の制限に達するまでデータを送信しません。 Nagleのアルゴリズムと同様に、ユーザーからのデータも累積しますが、ACKを受信するまでではなく、バッファーが一定の制限に達するまでです。これは、複数のデータブロックを送信するときに役立ちます。ただし、TCP_CORKを使用するときは注意が必要です。

2.6カーネルまで、これらのオプションは両方とも相互に排他的です。しかし、後のカーネルでは、両方が共存できます。そのような場合、TCP_CORKがより優先されます。

参照:

70
theB

_TCP_NODELAY_

Nagleのアルゴリズムを無効にして、TCP/IPネットワークを改善し、以前に送信したデータの確認応答を受信して​​蓄積パケットを送信するまで待機することにより、パケット数を減らします。

// tcp(7)マニュアルから:

_TCP_CORK_(または_TCP_NOPUSH_ FreeBSDの場合)

設定されている場合、部分的なフレームを送信しません。オプションが再びクリアされると、キューに入れられたすべての部分フレームが送信されます。これは、sendfile(2)を呼び出す前にヘッダーを追加する場合、またはスループットの最適化に役立ちます。現在実装されているように、出力が_TCP_CORK_によってコルクされる時間には** 200ミリ秒の上限があります。 この上限に達すると、キューに入れられたデータが自動的に送信されます。このオプションは、Linux 2.5.71以降のみ_TCP_NODELAY_と組み合わせることができます。このオプションは、移植性を目的としたコードでは使用しないでください。

21
Hussein Galal

これは最適化であり、他の最適化と同様です。

  1. 使用しないでください
  2. パフォーマンスが問題になるまで待ってから、ソケットレイテンシが間違いなくその原因であると判断し、テストによりこれが間違いなく修正されることが証明され、これが修正する最も簡単な方法です。

基本的に、目的は、sendfile()およびそのフレンドとともに、単一のフレームを使用できる複数のフレームを送信する必要を回避することです。

たとえば、Webサーバーでは、ヘッダーに続いてファイルの内容を送信します。ヘッダーはメモリ内で組み立てられ、ファイルはカーネルによって直接送信されます。 TCP_CORKを使用すると、TCP_NODELAYを使用してもヘッダーとファイルの先頭を単一のフレームで送信できます。そうしないと、最初のチャンクがすぐに送信されてしまいます。

7
MarkR

TCP_CORKはTCP_NODELAYの反対です。前者はパケット蓄積遅延を強制します。後者は無効にします。

0
fche