理想 reno 和理想 dctcp 的单流 cwnd-time 演化图如下:
很直观地展现出 dctcp 锯齿小很多,锯齿小意味着高效。
dctcp 利用交换机反馈而来的 ecn 可精确计算导致排队超过 k 的报文比例,减去这一比例的 inflight 就是合适的。但 dctcp 在 reno aimd 的动态过程之上,实际的多流情况很难在图像上标识,还要结合算术上分析:
阴影小三角形和梯形 abcd 的面积之比就是 alpha: 1 2 ( ( w + 1 ) + ( w + 1 ) ( 1 − α / 2 ) ) ∗ ( w + 1 ) ∗ α / 2 2 = α \dfrac{\frac{1}{2}}{\frac{((w+1)+(w+1)(1-\alpha/2))*(w+1)*\alpha/2}{2}}=\alpha 2((w+1)+(w+1)(1−α/2))∗(w+1)∗α/221=α ,现代网络的 cwnd 不会太小,可忽略 w 低阶项,解得 α = 2 w \alpha=\sqrt{\dfrac{2}{w}} α=w2 ,那么 (w + 1) - (w + 1)*(1 - alpha / 2) 就是锯齿的大小,将 alpha 代入,得到: ( w + 1 ) − ( w + 1 ) ∗ ( 1 − α / 2 ) = 2 ( w 2 + 2 w + 1 ) w / 2 ≈ 2 w 2 (w+1)-(w+1)*(1-\alpha/2)=\sqrt{\dfrac{2(w^2+2w+1)}{w}}/2\approx\dfrac{\sqrt{2w}}{2} (w+1)−(w+1)∗(1−α/2)=w2(w2+2w+1) /2≈22w 而对于标准 reno aimd,对应的上述值是 w + 1 2 \dfrac{w+1}{2} 2w+1 。简单比较一下二者:
简单的同步流场景,reno tcp 的最大 cwnd = (C * RTT + buffer) / N,而 dctcp 最大 cwnd = (C * RTT + K) / N。虽然只有一字之差,但 dctcp 并非只是 buffer = K 的替代,这正体现在上图的绿线中,这个根号 2w 的关系就来自于 dctcp 交换机反馈的精确信息,而如果没有这个信息,如黑线所示,reno 只能盲目以 0.5 为 md 系数猛降 cwnd 而造成大锯齿,cubic 虽改观,但本质不变。
从上述分解,可得 dctcp 拥塞周期为: T d c t c p = 2 ( C ∗ R T T + K ) / N 2 T_{dctcp}=\dfrac{\sqrt{2(C*RTT+K)/N}}{2} Tdctcp=22(C∗RTT+K)/N ,对应于 reno tcp,拥塞周期为: T r e n o = C ∗ R T T + B S i z e 2 N T_{reno}=\dfrac{C*RTT+BSize}{2N} Treno=2NC∗RTT+BSize ,C * RTT 为定值,姑且就让 BSize = K,变化 N,看看 dctcp 和 reno 拥塞周期的区别:
dctcp 的拥塞周期不随 N 变化,也不随 buffer 变化,这是 dctcp 可扩展的一面,另一面,观察队列变化可见排队时延的变化,对于 dctcp,queue 为: N ∗ ( ( w + 1 ) − ( w + 1 ) ∗ ( 1 − α / 2 ) ) ≈ N ∗ 2 w 2 = 2 N ( C ∗ R T T + K ) 2 N*((w+1)-(w+1)*(1-\alpha/2))\approx\dfrac{N*\sqrt{2w}}{2}=\dfrac{\sqrt{2N(C*RTT+K)}}{2} N∗((w+1)−(w+1)∗(1−α/2))≈2N∗2w =22N(C∗RTT+K) ,N 为流数量,开个根号就啥也没了,时延相对流的数量变化相当平缓,而对于 reno tcp,queue 完全受 buffer 限制,在 buffer 允许情况下,流数量越多,queue 越长,时延随流数量增加而明显增加。这就是 dctcp 的可扩展性的全部。
从以上分析可自然而然得到 dctcp 低时延结论,再次看 dctcp 和 reno tcp 的 queue 长度变化, Q L d c t c p = 2 N ( C ∗ R T T + K ) 2 QL_{dctcp}=\dfrac{\sqrt{2N(C*RTT+K)}}{2} QLdctcp=22N(C∗RTT+K) , Q L r e n o = C ∗ R T T + B S i z e 2 QL_{reno}=\dfrac{C*RTT+BSize}{2} QLreno=2C∗RTT+BSize ,将 N 等效为 BSize,可见 dctcp 队列的变化比 reno tcp 慢得多,很小的 K 值保持很小的排队时延就能容忍很宽的 C * RTT 范围,与此能力相对,reno tcp 需要 BSize 线性同步于 C * RTT,如果 C * RTT 很大而没有足够大的 buffer 与之匹配,reno aimd 一下子把 cwnd 降一半,把 inflight 降到不足 C * RTT,带宽将得不到有效利用。
我们发现,dctcp 的结论竟然就是异步 reno aimd 的结论,参见 dcn 交换机 buffer 的平方反比律。
大致就这么多。
如果把 dctcp 搬到广域网,满足 l4s 框架的交换机替代可 ecn 的 dcn 交换机,在 rtt 动态范围很大的广域网场景,配合 rtt-independence 特性解决小 rtt 流量侵略性问题: m × i n c r e a s e m e n t p e r A C K = 1 W v i r t m\times increasement_{perACK}=\dfrac{1}{W_{virt}} m×increasementperACK=Wvirt1,所以, i n c r e a s e m e n t p e r A C K = 1 m 1 W v i r t = 1 m 1 C ∗ R T T v i r t = 1 m 1 C ∗ m ∗ R T T = 1 m 2 1 W increasement_{perACK}=\dfrac{1}{m}\dfrac{1}{W_{virt}}=\dfrac{1}{m}\dfrac{1}{C*RTT_{virt}}=\dfrac{1}{m}\dfrac{1}{C*m*RTT}=\dfrac{1}{m^2}\dfrac{1}{W} increasementperACK=m1Wvirt1=m1C∗RTTvirt1=m1C∗m∗RTT1=m21W1,典型的一个 bdp 不变,把宽拉成长的操作。这就是一个低时延,低丢包,可扩展的算法,tcp prague,当然,它才刚起步。
我曾经对减小锯齿的方向不看好,因为我没有想到可以靠网络反馈信息,在纯端到端约束下,纯靠 capacity-search 的 aimd 变体根本无法减小锯齿,当它变钝,它必变长,当它变尖,它必变深,拉扯而已,却始终无法既短又钝,既尖又浅。vegas 在另一个方向也有时延不可扩展的问题难以解决。
随着带宽逐渐丰盈,应用也逐渐丰富,实时应用基本取代了离线应用,人们对时延的要求超过了对带宽的要求,宁取低时延而无需高带宽,带宽和时延的需求是不对称的,正如总量和种类的需求不对称一样,当人们吃饱了时,就无需越来越多的大米小麦了,但对饮食种类的需求是无止境的。
在这背景下,任何阻碍低时延的障碍都应被清除。起初人们认为网络分层模型是一个好模型,当时互操作大于一切,而如今低时延大于一切时,谁还在乎分层。网卡都可以 offloading tcp 了,交换机为什么不能呢。我在前几天评论到,在 rfc9000 quic 之前,人们把 quic 视作应用层,在 rfc9000 之后,quic 就无层了。
浙江温州皮鞋湿,下雨进水不会胖。