huitema / quic-in-space

Discuss QUIC in Space, produce draft
Other
1 stars 1 forks source link

congestion control algorithm #9

Open marcblanchet opened 10 months ago

marcblanchet commented 10 months ago

need a section on congestion control algorithm: cubic vs newreno vs bbr vs bbrv2

huitema commented 9 months ago

Yes. There are a few well known issues, and also a few subtle ones.

Reno embed time constants that makes it very inefficient on links with a large Bandwidth*Delay product. In congestion avoidance mode, Reno increases the bandwidth by one packet per RTT -- and then shrinks the window by half in case of packet loss. This is a well known issue, discussed for example by Sally Floyd in RFC3649. Bottom line, Reno cannot be used on deep space links.

Cubic is in theory a bit better, but there is a catch. Cubic grows the window as a function of time spent from the beginning of the epoch, with the formula:

Wcubic(t) = C * (t - K)**3 + Wmax

In that formula, C is a scaling constant determining the aggressiveness of the protocol in packets per second**3, and t is the time in seconds since the beginning of the epoch -- the recommended value being 0.4. The variable K in this formula acts as some kind of pseudo period. The window grows from an initial value at the beginning of the epoch to the nominal value "Wmax" after K seconds, after what it increases to probe the capacity of the link.

K is computed at the beginning of the epoch as:

K = cubic_root((Wmax - cwnd(epoch))/C)

In stable operation, Wmax is the congestion window at the end of the previous epoch, and "cwnd(epoch)" is the desired congestion window at the beginning of the epoch. Normally, cwnd(epoch) is set to beta*Wmax, the recommended value of beta being 0.7. We can assume that Wmax is the bandwidth*delay product, in packets, to get the formulas:

Wmax = BDP cwnd = beta*BDP K = cubic_root(BDP*(1-beta)/C)

Now, let's plot the values for a variety of delays:

C Beta Packet size (bytes) RTT(sec) Data rate (Mbps) BDP (packets) K (sec)
0.4 0.7 1500 0.1 1 8 2
0.4 0.7 1500 0.1 10 83 4
0.4 0.7 1500 0.1 100 833 9
0.4 0.7 1500 2 1 167 5
0.4 0.7 1500 2 10 1667 11
0.4 0.7 1500 2 100 16667 23
0.4 0.7 1500 600 1 50000 33
0.4 0.7 1500 600 10 500000 72
0.4 0.7 1500 600 100 5000000 155
0.4 0.7 1500 1200 0.1 100000 20
0.4 0.7 1500 1200 1 1000000 42
0.4 0.7 1500 1200 10 10000000 91
0.4 0.7 1500 1200 100 100000000 196

What we can see is that the value of K gets larger than the RTT as soon as the RTT is above several minutes. This is a very different behavior from the "terrestrial" or even "GEO" conditions, in which each "saw tooth" lasts many RTT. Basically, that means Cubic, too, is not going to work. Yes, it is possible to pick different values of C that restore some sanity, but that means creating a loop between RTT measurement and Cubic parameters, something that Cubic designers expressly did not want. They wanted the grow curve to be independent of RTT, so connections with different RTT would still be treated fairly.

BBR does perform much better, because it does not have constants with time dimension. It simply adapts to the RTT. It will work, as long as the RTT does not increase too much during the connection.