Nagleアルゴリズム なぐるあるごりずむ
Nagleアルゴリズム小さいパケットTCP遅延TCP_NODELAYバッファリング
Nagleアルゴリズムについて教えて
簡単に言うとこんな感じ!
小さなデータをまとめて送る「節約術」だよ。1バイトのデータを1パケットにすると、40バイトのTCPヘッダに対してペイロードが1バイトでめちゃくちゃ非効率。まとめて送ることで効率を上げてるんだけど、ゲームや対話型アプリでは邪魔になることもあるんだ!
Nagleアルゴリズムとは
Nagleアルゴリズムは、TCPで小さなパケット(Tinygram)を減らすためのバッファリング最適化です。1984年にJohn Nagleが提案し、RFC 896として標準化されました。
TCPヘッダは最低20バイトあります。もし1バイトのデータを1パケットで送ると、1バイトのペイロードに対して40バイト(TCPヘッダ20B + IPヘッダ20B)のオーバーヘッドが発生します。これをSilly Window Syndrome(愚かなウィンドウ症候群)と呼びます。
Nagleアルゴリズムは「未確認のデータ(送信済みACK待ち)がある間は、MSS未満のパケットをバッファに溜めてまとめて送る」というシンプルなルールで解決します。
Nagleアルゴリズムのルール
if データが MSS 以上
すぐに送信
else if ACK待ちのデータがない
すぐに送信
else
バッファに溜めて待機(ACKが来るかMSSが溜まるまで)
Nagleアルゴリズムの弊害
Nagleアルゴリズムは帯域効率を改善しますが、対話型アプリケーションでは問題になります。
| 問題が出るケース | 理由 |
|---|---|
| オンラインゲーム | キー入力を即座に送りたいのにバッファリングされる |
| ターミナル(SSH等) | キー入力が遅延してタイプが反映されるのに間が出る |
| 低遅延が重要なシステム | バッファ待ちが数十ms単位の遅延になる |
これらのケースではTCP_NODELAYオプションを設定してNagleアルゴリズムを無効化するのが一般的です。
import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# Nagleアルゴリズムを無効化
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
歴史と背景
- 1984年:John NagleがNagleアルゴリズムを提案。当時のARPANETでは小さいパケットが多く問題になっていた
- 1984年:RFC 896として標準化(後にRFC 1122に統合)
- 現在:ほぼすべてのOSでTCPのデフォルト機能として有効。ゲームエンジン・データベースドライバ等では通常無効化
遅延ACKとの関係
遅延ACK(Delayed ACK)もNagleアルゴリズムと組み合わさって問題になります。受信側が「40msほど待ってからACKを返す(ACKをまとめる)」機能で、Nagleアルゴリズムと組み合わさると最大40msのデッドロック的な遅延が発生することがあります。
対話型アプリではTCP_NODELAYでNagleを無効化するか、TCP_QUICKACKで遅延ACKを無効化することで解決できます。
関連する規格・RFC
| 規格・RFC番号 | 内容 |
|---|---|
| RFC 896 | Nagleアルゴリズムの原典 |
| RFC 1122 | インターネットホスト要件(Nagleを含むTCP要件) |
関連用語
- TCP — Nagleアルゴリズムが組み込まれるプロトコル
- MTU — MSSの計算に関係するフレームサイズ
- TCPウィンドウ制御 — 送信量を管理するフロー制御