下の記事で、BoliaというUDPベースのプロトコルとQUIC、TCPの比較が行われていました。
Boliaでは、QUIC(やTCPなど)で用いているのACKの仕組みをnetwork codingで代替しているようです。
無線などを使ったときに発生するランダムなロスが輻輳状態だと判断されてしまうことがあるのが課題で、それを解決するためにnetwork codingを使っているらしいです。
network codingについて
別な記事でシーケンスの説明がありました。
下の図では、P1、P2、P3、P4というパケットの代わりに、P1+P2、P2+P3、P3+P4、P2+P4、P1+P3+P4 という(おそらく)XORしたパケットを送っています。この場合はP3+P4のパケットが落ちてしまっても届いたパケットを使えばすべてのパケットを復号できるらしいです。
これによって、次に送るデータを決めるときにACKへの依存が必要なくなる点と、パケットリカバリーが自由にできるようになる点にメリットがあるようです。
また、個別のパケットが落ちたかどうかによるロスの検出ではなく、どのくらいのデータが通ったかによるロスの検出が行えるようになるらしいです。具体的には、送信側のスループットと受信側のグッドプットが想定の範囲内なら通常起こりうる転送エラーの範囲だと判断します。もし、差が大きいなら輻輳が発生したと判断するようです。
性能の比較
QUICの実装は、https://github.com/ngtcp2/ngtcp2、https://github.com/private-octopus/picoquic、https://github.com/facebookincubator/mvfst、https://github.com/facebook/proxygenを使用したようです。TCPの実装は、boost.asioと書かれているのでhttps://boostjp.github.io/tips/network/tcp.html っぽいです。
比較のために25回の連続したGETリクエストを行っています。固定されたリクエストのサイズ、遅延、パケットロスを設定してスループットを計測しています。
まずは、リクエストサイズが250KBytesで、ロス率がそれぞれ0.1%と0.2%の時の比較です。遅延5msの時のスループットは、QUIC > Bolia > TCPとなっています。遅延を大きくすると、Boliaのスループットが一番大きくなります。
リクエストサイズ17MBytesの場合は、ロス率0.2% 遅延5msの場合を除いて、Boliaのスループットが一番高くなっています。
著者の考察によると、リクエストサイズが小さい場合はslow startフェーズから抜けるまえに処理が終わってしまう、リクエストサイズが大きい時は輻輳制御とロス検出・リカバリーの仕組みによる差が出ている、とのことです。
あと、下の一文が読んでいて気になりました。
All QUIC implementations had 0-RTT enabled (the first request for each latency/packet loss point was 1-RTT and the remaining 0-RTT)
ある遅延・パケットロスの設定に対して最初のリクエストは1-RTTでそれ以降は0-RTTと書かれている。なので、コネクションを張りなおしているように読めました。
参考リンク
https://www.codavel.com/wp-content/uploads/2019/04/Draft_ArchitectureOverview.pdf