bic 旨在对 reno 改进,用二分逼近替换线性遍历逼近,时间规模从 O ( W m a x ) O(W_{max}) O(Wmax) 下降到 O ( ln W m a x ) O(\ln {W_{max}}) O(lnWmax),这是本质,而 cubic 可以看作对 bic 的 bugfix,解除了 rtt 依赖。在实现上,cubic 用一条以绝对时间 t 为自变量的数学曲线拟合 bic 绘制的折线。
因此,这条 cubic 曲线只能在大多数情况下拟合 bic,而不是所有情况,正如泰勒级数在某个点拟合任意曲线一样。用以下代码看究竟:
for n in range(1, len(times)):
if n % 1 == 0:
wx[n] = wmax_x + G*(n - n_x - 1 - K_x)**3
if wy[n-1] < wmax_y and wmax_y - wy[n-1] > I:
wy[n] = wy[n-1] + (wmax_y - wy[n-1])/B
elif wy[n-1] > wmax_y:
wy[n] = wy[n-1] + (wy[n-1] - wmax_y)/B
else:
wy[n] = wy[n-1] + I
else:
wx[n] = wx[n-1]
wy[n] = wy[n-1]
rx = wx[n]/C1
if rx < R:
tmp_x = wx[n]/R
else:
tmp_x = C1
x[n] = (1-a)*x[n-1] + a*tmp_x
ry = wy[n]/C2
if ry < R:
tmp_y = wy[n]/R
else:
tmp_y = C2
y[n] = (1-a)*y[n-1] + a*tmp_y
beta = 0.7
if inc1 and wx[n] > 2*C1*R:
C1 *= 2
inc1 = False
elif inc1 == False and wx[n] > 2*C1*R:
C1 /= 2
inc1 = True
if inc2 and wy[n] > 2*C2*R:
C2 *= 2
inc2 = False
elif inc2 == False and wy[n] > 2*C2*R:
C2 /= 2
inc2 = True
while wx[n] > 2*C1*R:
n_x = n
wmax_x = wx[n]
tmp = wmax_x*(1 - beta)/G
K_x = math.pow(tmp, 1/3)
wx[n] = (beta)*wx[n]
while wy[n] > 2*C2*R:
wmax_y = wy[n]
wy[n] = (beta)*wy[n]
我用不同的 bdp 模拟不同的 Wmax,展示其对曲线拟合效果的影响,x 为 cubic,y 为 bic:
事实上,就二分逼近而言,bic 是准确的,cubic 是近似的,它只做到 “与 rtt 无关,按照上凸逼近 Wmax,按照下凸 probe”,而并未执行二分逼近。
cubic 脱离了二分逼近,但保留了上凸逼近下凸 probe 的精髓:
- 上凸逼近保证逼近速度越来越慢,起初离 Wmax 远,快速逼近风险小,离 Wmax 越近风险越大越需要谨慎;
- 下凸 probe 确保了得寸进尺的哲学,既然有,大概率还会有。
但这些优势需要有代价来兑换,即 cubic 对待不同 Wmax 的不可扩展性,以下是我模拟不同的 Wmax 的动图:
如图所示,只要 C(建议为 0.4) 确定,cubic 曲线形状就确定了,Wmax 越大,逼近的时间越久,初始力度越大,曲线越瘦高,Wmax 越小,逼近时间越短,初始力度越小,曲线越矮胖,这也正是参数 K 的几何含义。另一方面,不管 Wmax 如何,probe 的过程都是一致的。
由于 cubic 曲线形状仅和 C 相关,而曲线的位置却和 Wmax 和 K 相关,而 K 又由 Wmax 决定,因此曲线位置仅和 Wmax 相关,以上分析直接导出了 cubic 算法 tcp friendliness 问题,即,当 Wmax 小到一定程度,cubic 曲线 x = K 左边足够平坦,以至于它的增窗效果还没有 y = I*x 标准 reno 算法更强,cubic 在这种情况下是有劣势的,而这种情况仅在 Wmax 足够小即短瘦管道时发生,于是乎,在这种情况下,cubic 退回到 reno,这就是 tcp friendliness 之解法。
小经理只是小经理,饲料标准降了,啥也不是。
浙江温州皮鞋湿,下雨进水不会胖。