このページの目次
ネットワークパフォーマンスとチューニング
アプリケーションバッファからTCP輻輳制御、NICオフロードまで——各層に調整可能なパラメータが存在します。BDPは帯域を最大限に活用するために必要なバッファサイズを決定し、BBRはモデルを用いてパケット損失検知に代わることで、バッファブローテッドなリンクにおいてCUBICよりも優れています。fq_codel/cakeはキューを能動的に管理し、バッファの過剰な埋め込みを防ぎます。
概要
ネット上で流通している「TCPチューニングの秘訣」の多くは、ユースケースを考慮せずに sysctl パラメータを羅列したものに過ぎません。効果的なチューニングには、たった一つの正道があります。アプリケーションからネットワークケーブルに至るまで、データが通過するキューを特定し、ボトルネックがどの層にあるかを測定し、その層のノブ(パラメータ)を調整することです。 パケットの送信パス上の各ノードがボトルネックとなる可能性があり、それぞれに独自の調整方法があります。
flowchart LR
APP["📦 アプリケーションバッファ<br><small>writeのブロックサイズ</small>"] --> SK["ソケットバッファ<br><small>tcp_wmem / tcp_rmem</small>"]
SK --> CC["TCP輻輳制御<br><small>cubic / bbr</small>"]
CC --> QD["qdiscキュー<br><small>fq_codel / cake</small>"]
QD --> DRV["ドライバリングバッファ<br><small>ethtool -G</small>"]
DRV --> NIC["NICオフロード<br><small>TSO / GSO / GRO</small>"]
NIC --> NET(("🌐 ネットワーク<br><small>ここでのキューは制御不可<br>→ bufferbloat</small>"))
classDef knob fill:#4493f81f,stroke:#4493f8,stroke-width:2px
classDef wild fill:#f8514926,stroke:#f85149,stroke-width:2.5px
class APP,SK,CC,QD,DRV,NIC knob
class NET wild
3つの典型的な問題は、それぞれ異なる層に対応しています。帯域が最大限に活用されない場合は、ソケットバッファがBDPより小さいか、輻輳アルゴリズムが不適切であることが多いです。ロード時にレイテンシが急上昇するのはキューの問題(bufferbloat)です。小包のスループット/CPU使用率の最大化は、割り込みとオフロードの問題です。以下、これら3つのカテゴリについて詳しく解説します。
帯域が最大限に活用されない: BDPとバッファサイズ
TCPがリンクの帯域を最大限に活用するためには、「伝送路上を飛行中」の未確認データがパイプ全体を満たす必要があります。パイプの容量は BDP(帯域幅 × RTT) であり、in-flight(送信中)の上限は min(cwnd, 受信ウィンドウ, 送信バッファ) によって制限されます。この3つの値のいずれかがBDPより小さい場合、帯域は最大限に活用されません。
| リンク | BDP | Linuxデフォルトで十分か |
|---|---|---|
| 1Gbps × 30ms(国内長距離) | 3.75 MB | 十分 (tcp_rmem max デフォルトは約6MB) |
| 1Gbps × 150ms(越境) | 18.75 MB | 不十分 |
| 10Gbps × 200ms | 250 MB | はるかに不十分 |
# トリプル: min / default / max —— 自動調整は min..max の間で伸縮する
検証方法: ss -ti で単一接続の cwnd、rtt、bytes_acked を確認する。cwnd がリンクの変動に合わせて変動するのではなく、バッファの上限に張り付いている場合、バッファがネックになっています。
注意: バッファは大きいほど良いわけではありません。BDPの低いリンクでは、大きなバッファは単にメモリを無駄に消費するだけであり、自身もボトルネックとなるデバイスではキューイングレイテンシを悪化させることがあります。実際の最大BDPに合わせて設定し、2倍の余裕を持たせれば十分です。
ロード時にレイテンシが急上昇: Bufferbloatとキュー管理
古典的な症状:アイドル時はpingが10msだが、ダウンロードを開始すると500msに上昇。原因は帯域幅ではなくキューにあります。パス上の何らかのデバイス(多くの場合、家庭用ルーターやONU)が巨大なFIFOバッファを持っており、CUBICのようなパケット損失駆動型のアルゴリズムは、それが満たされるまでパケットを送り続けます。その結果、すべてのトラフィックがこの深いキューで待機することになります。
自分で制御可能な両端では、FIFOの代わりに AQM(アクティブキュー管理) を使用します。
- fq_codel = 公平キュー + CoDel。CoDelの考え方は、パケットの滞留時間に注目することです。5msを継続的に超えると、パケットをドロップし始めます(キューの先頭からドロップし、シグナルが速く伝わる)。これにより送信側の速度低下を促し、キューが短くなればレイテンシは自然に低下します。公平キュー部分は、大きなフロー(エレファントフロー)が隣接するSSH接続を飢えさせないように保証します。
- cake は fq_codel の実装上の改良版です:整形器を内蔵(
bandwidthを実際のアップリンク速度よりわずかに低く設定し、キューをONUから自デバイスへ戻す)、ホストごとの分離(1台のデバイスでBTを起動しても家族全員に影響を与えない)、DiffServ対応。
送信側で bbr と組み合わせると最も効果的です。BBRは元々キューを満たしません(原理は TCP Deep Dive の輻輳制御セクションを参照)。
一般的なTCPノブ
| ノブ | 役割 | 調整すべきタイミング | リスク |
|---|---|---|---|
tcp_congestion_control=bbr | モデル駆動型輻輳制御 | 長距離/太いリンク、パケット損失あり、bufferbloat なリンク | CUBICフローとの共存時の公平性(v1) |
tcp_fastopen=3 | SYNパケットにデータを含め、リターンユーザーはRTTを1回節約 | 短時間接続が密集するAPIサービス | 中間ボックスがTFOパケットをドロップする可能性 |
tcp_tw_reuse=1 | クライアント側でTIME_WAIT状態を再利用 | 高並列短時間接続のクライアント | クライアント側でのみ安全。すでに削除された tw_recycle を触らないこと |
somaxconn + tcp_max_syn_backlog | 完全/半接続キューの深さ | ss -lnt で listen キューの溢れを確認した場合 | キューを深くするだけで、処理しきれない場合はスケーリングが必要 |
tcp_notsent_lowat=16384 | 送信バッファ内の「まだ送信されていない」量を制限 | レイテンシが敏感なストリーミングアプリケーション | 極端なスループットがわずかに低下 |
原則:変更するたびに、ベンチマークで比較する。ノブ同士は相互作用するため、すべてを一度に変更するのは調整していないのと同じです。
小包とCPU: NICオフロード
10Gbps環境では、1秒間に百万パケットに達することもあり、パケットごとの割り込みでは、帯域幅が枯渇する前にCPUが先にパンクします。アプローチはバッチ処理——パケットの断片化や結合をカーネルからNICへ移すことです。
| オフロード | 方向 | 動作 |
|---|---|---|
| TSO | 送信 | カーネルが64KBの大きなブロックをNICに渡し、NICがハードウェアでMSSサイズに分割 |
| GSO | 送信 | TSOのソフトウェアフォールバック(仮想NIC、TSO非対応ハードウェア)、ドライバの手前で最後の瞬間まで分割しない |
| GRO | 受信 | 同一フローの連続した小包を結合して大きなブロックにし、プロトコルスタックに渡すことで、割り込みと走査を節約 |
|
tcpdumpの古典的な落とし穴: 64KBの「巨大パケット」がキャプチャされていても、それは異常ではありません。TSO/GROが有効になっており、キャプチャポイントが分割前/結合後にあるためです。実際のオンライン通信ではMTUサイズで転送されます。逆に、オフロードが問題を引き起こしている(特に仮想環境でのチェックサムエラー)と疑われる場合は、まず ethtool -K ... off で排除します。
ボトルネックの特定順序
- ベースライン:
iperf3 -c <server> -Rで双方向を測定し、純粋な帯域幅を取得——まずボトルネックがネットワークにあることを確認します。 - ロード下でのレイテンシ測定: iperf3 を実行しながら
pingを実行し、レイテンシが10倍に増加 → bufferbloat、キューを調整。 - 単一接続の確認:
ss -tiの cwnd/rtt/retrans を確認。cwnd が上がらない場合はバッファと輻輳アルゴリズムを確認、retrans が多い場合はリンク品質を確認。 - システム確認:
nstat -a | grep -i retrans、ethtool -S eth0 | grep -i drop(NIC層でのパケットドロップ)、softnet_statのバックプレッシャー。 - 1つの変数を変更し、ステップ1に戻ります。
体系的なパケットキャプチャ分析については tcpdump と Wireshark、トラブルシューティングのアプローチについては ネットワーク障害診断方法论 を参照してください。
参考文献
- BBR: github.com/google/bbr · RFC 9438
- fq_codel/CoDel: RFC 8290, RFC 8289 · bufferbloat.net
- cake: man tc-cake · RFC 8290 の実装版
- Brendan Gregg: 「Systems Performance」第10章 (Network)
Keywords: BDP, BBR, CUBIC, bufferbloat, fq_codel, cake, AQM, TCPチューニング, tcp_rmem, TSO, GSO, GRO, ethtool, iperf3