TCP/UDPの仕組み

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 896Nagleアルゴリズムの原典
RFC 1122インターネットホスト要件(Nagleを含むTCP要件)

関連用語

  • TCP — Nagleアルゴリズムが組み込まれるプロトコル
  • MTU — MSSの計算に関係するフレームサイズ
  • TCPウィンドウ制御 — 送信量を管理するフロー制御