TCPのスロースタート・輻輳回避は帯域とRTTでどう変わる?高帯域・高遅延ネットワークの通信速度をわかりやすく解説

通信プロトコル

TCPでは、送信側がネットワークへ一度に流し込むデータ量を調整するために、スロースタートや輻輳回避といった輻輳制御が使われます。これらの仕組みはネットワークを混雑させないために重要ですが、回線帯域やRTT(Round Trip Time)が大きく異なる環境では、同じTCPでも実効速度の立ち上がり方や到達できるスループットが大きく変わります。

特に重要なのが、帯域が大きいほど十分な量の未確認データをネットワーク上に保持する必要があり、RTTが長いほどその量を増やすためのフィードバックに時間がかかるという点です。この関係は帯域遅延積(Bandwidth-Delay Product、BDP)で理解すると整理しやすくなります。

この記事では、TCPのスロースタートと輻輳回避がどのように動き、低遅延LAN、高帯域WAN、衛星回線などで通信速度へどのような影響を与えるのかを、具体的な数値例とともに解説します。

  1. TCPの通信速度を左右する輻輳ウィンドウとは
  2. スロースタートは通信開始直後の送信量を急速に増やす
  3. RTTが大きいほどスロースタートの立ち上がりが遅くなる
  4. 帯域が大きいほど必要なウィンドウサイズも大きくなる
  5. 高帯域・高RTTのネットワークがTCPにとって難しい理由
  6. 低帯域・低RTT環境ではスロースタートの影響は比較的小さい
  7. 輻輳回避ではウィンドウ増加がスロースタートより穏やかになる
  8. 高RTT環境ではパケット損失からの回復も遅くなりやすい
  9. パケットロスがあると高RTT回線ではさらに不利になる
  10. 具体例1:1Gbps・RTT1msのLAN
  11. 具体例2:1Gbps・RTT100msの長距離WAN
  12. 具体例3:衛星回線のような高RTT環境
  13. 短い通信ほど高RTTの影響を受けやすい
  14. 帯域を増やしても通信時間があまり改善しない場合がある
  15. TCPウィンドウスケーリングが高BDP環境で重要になる
  16. 現在のTCPはすべて同じ輻輳回避アルゴリズムではない
  17. BBRは損失だけでなく帯域とRTTを推定する考え方を採用する
  18. スロースタートの初期ウィンドウも昔より大きくなっている
  19. パケット損失がスループットへ与える影響はアルゴリズムによって違う
  20. バッファが大きすぎても遅くなる「Bufferbloat」
  21. 並列TCP接続を使うと見かけ上速度が上がることがある
  22. 通信速度を調べるときに確認したい項目
  23. 帯域とRTTの組み合わせによる傾向を整理
  24. まとめ:TCPでは帯域だけでなくRTTとBDPが通信速度を大きく左右する

TCPの通信速度を左右する輻輳ウィンドウとは

TCP送信側は、ACKを待たずに無制限のデータを送るわけではありません。ネットワーク混雑を避けるため、cwndと呼ばれる輻輳ウィンドウによって、未確認のまま送信できるデータ量を制御します。

実際に送信できる量は輻輳ウィンドウだけでなく、受信側が通知する受信ウィンドウなどにも制約されますが、輻輳制御を理解するうえでは「cwndが小さいと一度に送れるデータが少なく、cwndが大きくなるほど高いスループットを出しやすい」と考えると分かりやすくなります。

単純化すると、ウィンドウがボトルネックになっている状況のスループットは、おおよそ次の関係で考えられます。

スループット ≒ ウィンドウサイズ ÷ RTT

たとえば同じ1MBの送信ウィンドウでも、RTTが10msなら理論上は約100MB/s相当のデータを回せますが、RTTが100msなら約10MB/s相当です。RTTが大きい環境では、同じ通信速度を維持するためにより大きなウィンドウが必要になります。

スロースタートは通信開始直後の送信量を急速に増やす

TCPは接続開始時点でネットワークがどの程度の負荷に耐えられるか分かりません。そのため最初から回線容量いっぱいまで送るのではなく、比較的小さな輻輳ウィンドウから開始し、ACKが返るにつれて送信可能量を増加させます。

これがスロースタートです。名前に「スロー」とありますが、増加の仕方そのものは遅いわけではありません。一般的にはACKが順調に返っている間、RTTごとにcwndが概ね指数関数的に増加するため、短期間で送信量を拡大できます。

ただし、この「RTTごとに増える」という性質が重要です。同じ回数だけウィンドウを拡大する場合でも、RTTが10msなら短時間で進みますが、RTTが200msなら20倍の時間がかかります。

RTTが大きいほどスロースタートの立ち上がりが遅くなる

たとえば説明を簡単にするため、初期輻輳ウィンドウを約14KBと仮定し、各RTTでほぼ2倍になるとします。

開始時:約14KB
1 RTT後:約28KB
2 RTT後:約56KB
3 RTT後:約112KB
4 RTT後:約224KB
5 RTT後:約448KB
6 RTT後:約896KB

6RTTかけて約900KBまで増えるとすると、RTTが10msなら約60msですが、RTTが100msなら約600ms、RTTが500msなら約3秒必要です。

つまり、高RTT環境では回線そのものが高速でも、TCPが十分な送信量へ拡大するまで時間がかかるということです。

この影響は特に短い通信で目立ちます。数十KBから数百KB程度の転送なら、cwndが十分大きくなる前に通信が終了する可能性があるため、高帯域回線を契約していても最大速度をほとんど利用できない場合があります。

帯域が大きいほど必要なウィンドウサイズも大きくなる

高帯域回線では大量のデータを高速で送れますが、その能力をTCPで使い切るには、ネットワーク上に十分な量の未確認データを存在させる必要があります。

この必要量を考えるときに使われるのが帯域遅延積(BDP)です。

BDP = 帯域 × RTT

たとえば100Mbpsの回線でRTTが10msなら、BDPは次のようになります。

100Mbps × 0.01秒 = 1Mbit ≒ 125KB

一方、1GbpsでRTTが100msなら次のようになります。

1Gbps × 0.1秒 = 100Mbit ≒ 12.5MB

後者では、理想的に回線を埋めるためには概算で12.5MB程度のデータを飛行中の状態にする必要があります。このため高帯域・高RTTの組み合わせでは非常に大きなウィンドウが必要になります。

高帯域・高RTTのネットワークがTCPにとって難しい理由

帯域が高くRTTも大きいネットワークは、一般にLong Fat Network、略してLFNと呼ばれる文脈で議論されることがあります。

たとえば東京と海外拠点の間に1Gbps級のネットワークがあっても、RTTが150msあるとします。その場合のBDPは約150Mbit、つまり約18.75MBです。

もしcwndが1MBしかなければ、単純計算では最大スループットは次の程度です。

1MB ÷ 0.15秒 ≒ 6.67MB/s ≒ 53Mbps

物理回線が1Gbpsでも、十分なウィンドウが確保されなければ53Mbps程度しか出せない可能性があるということです。

この例からも、回線速度だけではTCPの実効速度を判断できず、RTTとウィンドウサイズを合わせて見る必要があることが分かります。

低帯域・低RTT環境ではスロースタートの影響は比較的小さい

同一LAN内などRTTが非常に小さい環境では、ACKが短時間で返ってくるため、TCPは輻輳ウィンドウを素早く増やせます。

また低帯域回線では、回線を埋めるために必要なBDPそのものが小さいため、それほど大きなcwndを必要としません。

たとえば100Mbps・RTT1msならBDPは約12.5KBです。実際のTCP実装の初期ウィンドウやネットワーク条件にもよりますが、非常に少ないデータ量でも回線容量へ近づきやすい環境です。

そのため同じTCPでも、「近距離のLANではすぐ速度が出るのに、遠距離の高速回線では思ったほど速度が出ない」という違いが生じます。

輻輳回避ではウィンドウ増加がスロースタートより穏やかになる

スロースタートでいつまでも指数関数的に送信量を増やし続けると、いずれネットワーク容量を大きく超えてしまいます。そのため一定の段階や輻輳検出後には、より慎重に送信量を増やす輻輳回避へ移ります。

古典的なTCP Reno系の説明では、輻輳回避中のcwndは概ね1RTTあたり1MSS程度ずつ増加する加法増加として理解できます。パケット損失などによって輻輳を検出するとcwndを減らし、再び慎重に増加させます。

ここでもRTTが重要です。1RTTごとに増加するので、RTTが長い通信ほど同じウィンドウサイズまで回復するのに時間がかかります。

高RTT環境ではパケット損失からの回復も遅くなりやすい

高帯域・高RTT環境では、パケット損失によってcwndが減少した後の回復にも時間がかかります。

たとえば輻輳検出によって大きくcwndを減らし、その後RTT単位で少しずつ増やす方式では、RTTが20msの通信より200msの通信のほうが回復速度は遅くなります。

さらに高帯域回線では、回線を埋めるために必要なウィンドウ自体が大きいため、減少前の水準へ戻すまで多数のRTTが必要になることがあります。

このため古典的な損失ベースのTCPでは、高帯域・高遅延の環境ほど単一のパケット損失が長時間のスループット低下につながりやすいという問題があります。

パケットロスがあると高RTT回線ではさらに不利になる

TCPでは歴史的にパケット損失をネットワーク輻輳の重要なシグナルとして扱ってきました。そのため損失が検出されると、送信量を減少させます。

有線LANのようにRTTが短くロス率も非常に低い環境では影響が限定的なことがありますが、衛星通信、無線ネットワーク、長距離WANなどでは事情が異なります。

通信エラーなど、必ずしもルーターのキュー混雑が原因ではない損失でもTCPが輻輳として反応すれば、送信量を減らします。RTTが大きい環境ではその後の再送やウィンドウ回復にも時間がかかるため、実効速度が大幅に下がる場合があります。

具体例1:1Gbps・RTT1msのLAN

1GbpsでRTT1msのネットワークなら、BDPは次の程度です。

1Gbps × 0.001秒 = 1Mbit ≒ 125KB

必要な飛行中データ量は約125KBなので、現代的なTCP環境なら比較的早い段階で十分なウィンドウへ到達できます。

スロースタートもRTT単位で高速に進むため、大容量転送なら早期に高スループットへ近づきやすい環境です。

具体例2:1Gbps・RTT100msの長距離WAN

同じ1GbpsでもRTTが100msになると、BDPは約12.5MBになります。

1Gbps × 0.1秒 = 100Mbit = 12.5MB

つまり約12.5MB規模のデータをACK待ちの状態で送れるだけのウィンドウがなければ、1Gbpsの帯域を十分利用できません。

さらに接続直後はcwndが小さいため、スロースタートによって12.5MB近くまで拡大するまで複数RTTが必要になります。

大容量ファイルなら最終的に速度が伸びる可能性がありますが、小容量ファイルを何度も新しいTCP接続で送るような通信では、高速回線の能力を十分使う前に各転送が終わってしまうことがあります。

具体例3:衛星回線のような高RTT環境

衛星通信などでは、物理的な伝搬距離の影響によってRTTが数百msになることがあります。

仮に帯域が100Mbps、RTTが600msならBDPは次のようになります。

100Mbps × 0.6秒 = 60Mbit ≒ 7.5MB

100Mbpsという帯域だけを見るとそれほど巨大には見えませんが、RTTが600msあるため、回線を効率よく利用するには約7.5MBの飛行中データが必要です。

さらにACKを利用したウィンドウ成長も1往復に600msかかるため、通信開始直後や損失後の回復が低遅延ネットワークより大幅に遅くなります。

短い通信ほど高RTTの影響を受けやすい

スロースタートによる性能低下は、大容量ファイル転送だけでなく、むしろ短い通信で重要になる場合があります。

たとえば数十KBのHTTPレスポンスを取得するケースでは、TCPが大きなcwndへ成長する前に転送自体が終了します。そのため最大帯域が1Gbpsでも10Gbpsでも、RTTが大きければ応答完了までの時間はあまり短縮されないことがあります。

Webページのように多数の小さなリソースを取得する用途では、接続確立、暗号化ハンドシェイク、要求・応答などの往復遅延も影響します。

このためユーザーが感じるWebの速さは「回線が何Gbpsか」だけでは決まらず、RTTも非常に重要な指標です。

帯域を増やしても通信時間があまり改善しない場合がある

「100Mbpsから1Gbpsへ変更すればすべての通信が10倍速くなる」とは限りません。

たとえば少量データを送って応答を待つ処理では、データ転送時間よりRTTのほうが支配的になることがあります。

また、単一TCP接続がウィンドウ制約や輻輳制御によって100Mbps程度しか利用できていないなら、物理回線を10Gbpsへ変更しても、そのままでは10Gbpsのスループットへ到達しません。

高帯域化の効果を引き出すには、受信ウィンドウ、ウィンドウスケーリング、輻輳制御アルゴリズム、バッファサイズ、パケットロスなども確認する必要があります。

TCPウィンドウスケーリングが高BDP環境で重要になる

古典的なTCPヘッダーのウィンドウフィールドは16ビットで、そのままでは最大65,535バイト程度です。高帯域・高RTT環境ではこれでは小さすぎます。

そこでTCP Window Scale Optionによって、より大きな受信ウィンドウを利用できる仕組みが標準化されています。[参照] RFC 7323「TCP Extensions for High Performance」

現代の主要OSではウィンドウスケーリングや自動バッファ調整が一般的に利用されますが、途中の機器、OS設定、アプリケーションのソケットバッファなどによって制約される場合があります。

高帯域・高RTT環境で速度が出ない場合には、cwndだけでなく受信側ウィンドウがボトルネックになっていないかも確認する必要があります。

現在のTCPはすべて同じ輻輳回避アルゴリズムではない

「TCPの輻輳回避」といっても、現在のOSがすべて古典的なTCP Renoだけを使っているわけではありません。

LinuxではCUBICが広く利用されており、高帯域・高遅延ネットワークでも従来のRenoよりウィンドウを効率よく成長させることを目的としています。CUBICはウィンドウ成長を時間の3次関数によって制御し、RTTの違いによる不公平を抑えることも設計目標の一つです。[参照] RFC 9438「CUBIC for Fast and Long-Distance Networks」

そのため、実際の通信性能を考えるときは「TCPだから必ずReno型の1RTTあたり1MSS増加」と決めつけず、OSがどの輻輳制御アルゴリズムを使用しているか確認することが重要です。

BBRは損失だけでなく帯域とRTTを推定する考え方を採用する

代表的な別アプローチとしてBBRがあります。BBRは主としてパケット損失を基準に送信量を調節する従来型アルゴリズムとは異なり、ボトルネック帯域とRTTを推定して送信レートを制御する考え方を採用しています。

このため、高帯域・高RTT環境や一定のランダムロスが存在する環境で、損失ベースのアルゴリズムとは異なる性能特性を示します。

ただしBBRを使えばあらゆる環境で必ず高速になるという意味ではありません。公平性、キューイング、他フローとの競合、実装バージョンなどを含めて評価する必要があります。

重要なのは、現代のTCP性能はスロースタートと輻輳回避という基本概念を共通に持ちながらも、具体的なウィンドウ成長や輻輳判定の方法がアルゴリズムによって異なるという点です。

スロースタートの初期ウィンドウも昔より大きくなっている

TCPの説明では「最初は1セグメントから開始して倍々に増える」と説明されることがありますが、これは歴史的な理解としては有用でも、現在の一般的な実装をそのまま表すとは限りません。

RFC 6928ではTCPの初期ウィンドウを最大10セグメントへ拡大することが提案され、現在ではこの考え方が広く利用されています。[参照] RFC 6928「Increasing TCP’s Initial Window」

初期ウィンドウを大きくすると、小さなWebレスポンスなどを少ないRTTで送信し終えやすくなるため、特に高RTT環境の短い通信で効果があります。

それでも巨大なBDPを持つ高帯域・高遅延回線では、初期ウィンドウだけで回線を埋めることはできないため、その後のウィンドウ成長は依然として重要です。

パケット損失がスループットへ与える影響はアルゴリズムによって違う

古典的なTCP Renoの性能モデルでは、損失率が高くなるにつれてスループットが大きく低下し、RTTが長いほどさらに不利になる関係が知られています。

そのため、同じ1%未満の小さなロスでも、低RTTのLANと高RTTの長距離WANでは体感する速度低下が大きく異なることがあります。

CUBICなどの高速ネットワーク向けアルゴリズムはこうした問題を改善する目的がありますが、ロスや再送が大量に起きれば当然性能は低下します。

高帯域WANで速度を測定するときには、平均帯域だけでなく、RTT、パケットロス率、再送数も同時に確認することが重要です。

バッファが大きすぎても遅くなる「Bufferbloat」

高スループットを得るためにネットワーク機器のバッファを無制限に大きくすればよいわけではありません。

ルーターや回線終端装置のキューへ大量のパケットが滞留すると、パケットは失われにくくてもRTTが大きく増加することがあります。これがBufferbloatと呼ばれる問題です。

たとえば通常20msだったRTTが、大量アップロード中だけ300msになる場合があります。この状態ではTCPのACKフィードバックも遅れ、Web閲覧やオンライン会議などの応答性も悪化します。

そのため「ロスをなくすためにバッファを増やす」だけではなく、AQMなどによって適切にキューを管理することも現代のネットワークでは重要です。

並列TCP接続を使うと見かけ上速度が上がることがある

単一TCP接続で十分な速度が出ない場合、複数のTCP接続を並列にすると合計スループットが上がることがあります。

これは各接続が独立したcwndを持つため、合計するとより多くのデータをネットワークへ送れるからです。ダウンロードツールなどが複数接続を利用する理由の一つです。

ただし、並列化によってネットワーク全体の帯域が増えるわけではありません。また他のTCPフローに対して不公平になる場合もあるため、「単一TCPが遅ければ接続数を増やせばよい」と一般化するのは適切ではありません。

通信速度を調べるときに確認したい項目

高帯域回線なのにTCP速度が出ない場合は、回線契約上の最大速度だけを見るのではなく、複数の要素を確認します。

確認項目 通信速度への主な影響
帯域 理論上送信できる最大データ量
RTT ACKのフィードバック速度・ウィンドウ成長速度
BDP 回線を埋めるために必要な飛行中データ量
cwnd 輻輳制御上送信できる未確認データ量
受信ウィンドウ 受信側が許可する未確認データ量
パケットロス 再送・cwnd減少の原因
輻輳制御方式 CUBIC、BBRなどで成長特性が異なる
転送サイズ 短い通信では最大速度へ到達する前に終了しやすい

特にiperf3などで性能測定を行う場合は、スループットだけでなく再送数や並列数も確認し、pingなどでRTTも測定すると原因を切り分けやすくなります。

帯域とRTTの組み合わせによる傾向を整理

環境 TCPの傾向
低帯域・低RTT 必要なBDPが小さく、比較的すぐ帯域を利用しやすい
高帯域・低RTT BDPは増えるがACKが早く、cwndを成長させやすい
低帯域・高RTT 帯域は小さいが、応答遅延や短い通信へのRTTの影響が大きい
高帯域・高RTT 巨大なBDPが必要で、スロースタートや損失後の回復が課題になりやすい

最もTCPのチューニングが重要になりやすいのが、高帯域・高RTTの組み合わせです。長距離データセンター間通信、国際回線、大容量クラウド転送などが代表例です。

まとめ:TCPでは帯域だけでなくRTTとBDPが通信速度を大きく左右する

TCPのスロースタートではACKが返るにつれてcwndを急速に増やしますが、その成長はRTT単位で進みます。そのためRTTが大きいほど十分な送信量へ到達するまで時間がかかり、特に短い通信で速度が伸びにくくなります。

また帯域が大きくなるほど回線を埋めるために必要なデータ量も増えます。必要な量は帯域 × RTTで表される帯域遅延積(BDP)で考えることができ、高帯域・高RTTでは数MBから数十MB以上のウィンドウが必要になることもあります。

輻輳回避へ移行すると送信量の増加はスロースタートより慎重になります。特に古典的な損失ベースの方式では、パケット損失によってcwndが低下した後、高RTT環境ほど元のスループットへ戻るまで時間がかかります。

一方、現在はCUBICやBBRなど、従来のRenoとは異なる特性を持つ輻輳制御アルゴリズムも利用されています。そのため実環境の性能を評価するときは、帯域、RTT、BDP、パケットロス、送受信ウィンドウ、輻輳制御アルゴリズム、転送サイズを合わせて確認することが重要です。

要するに、低RTT環境ではTCPは比較的素早く高速化できますが、高RTT環境ではフィードバックそのものが遅くなります。そして帯域まで大きい場合には巨大なウィンドウが必要になるため、スロースタートや輻輳回避の性質が通信速度へより強く表れると理解すると、TCPの性能差を整理しやすくなります。

コメント

タイトルとURLをコピーしました