漫谈TCP High Speed与TCP Africa(TCP China)

自春节假期开启了漫谈TCP,很多想法都想往这上面靠,本周单休,早上4点起来写一篇春节假期没来得及写完的,今天这个关于HSTCP和TCP Africa的话题也归入漫谈了,实际上也真的是漫谈。

很多人看到TCP的一系列参数就身不由己地想魔改,包括我自己曾经就是这样,比如把3改成2,把10改成30,如此这般,这种魔改的目标在心理上几乎总是为了提高传输性能,这就是所谓的TCP加速。

除了超发,几乎没有别的简单的手段来加速TCP,而简单把数值改大改小就能实现超发,这种仅仅属于网吧级的,一般玩游戏的人就能改,改完之后还要狂妄一阵子,显得自己跟个真正的黑客一样。

稍微精巧一点的,就是测量一下带宽,测量一下RTT,然后学着那些正儿八经的paper的样子煞有其事地引入一个 α \alpha α,一般 β \beta β之类的经验参数,鼓捣一个越晦涩越好的公式,这种属于BAT级的,大型互联网公司一般都用这种方法来魔改TCP,以天为周期迭代,不然完不成KPI,这种改完之后也会狂妄一阵子,比如那些谁谁谁天天就知道鄙视别人。

所谓魔改,就是没有任何理由地修改,让你觉得是在玩魔术,把10改成了30,却不说为什么这样改,让人云里雾里地深信这里面一定藏有深不可测的道道,从而让这些魔改TCP的人得以拿着这点儿东西招摇撞骗。

那么你听说过TCP HighSpped(HSTCP)吗?或者TCP Africa也差不多,看到下面的这个时,你准备怎么魔改:

static const struct hstcp_aimd_val {
        unsigned int cwnd;
        unsigned int md;
} hstcp_aimd_vals[] = {
        {     38,  128, /*  0.50 */ },
        {    118,  112, /*  0.44 */ },
        {    221,  104, /*  0.41 */ },
        {    347,   98, /*  0.38 */ },
        {    495,   93, /*  0.37 */ },
        {    663,   89, /*  0.35 */ },
        {    851,   86, /*  0.34 */ },
        {   1058,   83, /*  0.33 */ },
        {   1284,   81, /*  0.32 */ },
	...

HSTCP作为一种优化版的AIMD算法,它到底是如何优化Reno的,背后的理论依据是什么,魔改真的有效吗?本文来漫谈。

先从朴素的Reno开始。

我们知道Reno是一个典型的AIMD算法。Reno算法过程非常简单:

  • AI过程:拥塞避免阶段每一个RTT增加一个窗口。
  • MD过程:遭遇丢包时,窗口减到原来的一半。

但AIMD是一个一般性的算法,Reno只是其中的一个实例解而已,因此把AIMD的描述一般化是合适的:

  • AI过程:拥塞避免阶段每一个RTT增加 a a a个窗口。
  • MD过程:遭遇丢包时,窗口减少原来的 b b b,即减少到 ( 1 − b ) W (1-b)W (1b)W

我们看它锯齿状的cwnd-time图:
在这里插入图片描述

设丢包时最大的窗口为 W W W, 很容易算出在一个 “锯齿周期” 中,从 ( 1 − b ) W (1-b)W (1b)W开始增窗,截止到丢包一共增长了 b W bW bW个窗口,因此一个周期持续了 b W a + 1 \dfrac{bW}{a}+1 abW+1个RTT的时间,一个锯齿围成的面积就是一个周期内传输的数据包数量:

N = ( b W a + 1 ) ( 1 − b ) W + 1 2 ( b W a + 1 ) ( 1 − b ) W N=(\dfrac{bW}{a}+1)(1-b)W+\dfrac{1}{2}(\dfrac{bW}{a}+1)(1-b)W N=(abW+1)(1b)W+21(abW+1)(1b)W

理想情况下的理想锯齿,每一个周期丢包1个,那么丢包率很容易求得:

P = 1 N P=\dfrac{1}{N} P=N1

N N N带入,化简。关于如何化简,这里技巧来了。

我们知道,在一个理想的AIMD系统中,如果我们把丢包的原因统一归为buffer overflow,那么什么时候丢包就完全取决于buffer的大小,换句话说,buffer的大小决定了丢包率,那么很显然,buffer的大小决定了一个周期内发送的数据量,即 N N N N N N是通过最大窗口 W W W计算所得。因此我们需要得到的是 P P P W W W的关系,将 W W W作为主元化简,得到:

P = 2 a b ( 2 − b ) W 2 + a ( 2 − b ) W P=\dfrac{2a}{b(2-b)W^2+a(2-b)W} P=b(2b)W2+a(2b)W2a

这是一个关于 W W W的一元二次方程,这里给出 W W W的一个近似解(忽略了一次项):

W = 2 a b ( 2 − b ) P W=\sqrt{\dfrac{2a}{b(2-b)P}} W=b(2b)P2a

现在计算一下发送带宽,我们用其定义来计算,即 单位时间内发送的数据量 ,看起来好像是我们计算出一个RTT内发送的数据量 a a a,然后除以RTT就是了,然而并不是!

在AIMD的一个周期中,发送带宽并不是固定的,很显然发包量是一开始很小然后逐渐增加的,因此我们需要计算的是在一个RTT内的平均发送量:

T R T T = ( 1 − b ) W + W 2 T_{RTT}=\dfrac{(1-b)W+W}{2} TRTT=2(1b)W+W

除以RTT,就是平均带宽了:

T = 2 − b 2 × R T T W T=\dfrac{2-b}{2\times RTT}W T=2×RTT2bW

把刚才那个 W W W的近似解代入,就会得到一个神奇的关系:

T = 1 R T T a ( 2 − b ) 2 b 1 P T=\dfrac{1}{RTT}\sqrt{\dfrac{a(2-b)}{2b}}\dfrac{1}{\sqrt{P}} T=RTT12ba(2b) P 1

这个式子让人看不出什么所以然,原因是那些 a a a b b b R T T RTT RTT,根号混淆了人的试听,不妨把Reno的参数代入,即 a = 1 a=1 a=1 b = 0.5 b=0.5 b=0.5,我们就能得到一个清晰的式子:

T r e n o = 1.22 R T T P − 1 2 T_{reno}=\dfrac{1.22}{RTT}P^{-\frac{1}{2}} Treno=RTT1.22P21

在这里我们先打住一下,看看有什么好玩的。

上面的 T r e n o T_{reno} Treno表达式可以明显看出,Reno的吞吐率和丢包率 P P P以及RTT相关,显然丢包率一定时,RTT越大,吞吐率越小,而丢包率 P P P在理想情形下是buffer的大小决定的,那么现实情况如何呢?

现实情况下,往往会有大量的非拥塞的随机丢包,比如误码,信号衰减等,这些独立的随机事件的发生和时间是正相关的,也就是说,RTT越大,在一个锯齿周期内发生随机丢包的概率就越大,而Reno并不识别随机丢包,因此长RTT对Reno的吞吐率性能无疑是一个减分项,记住这一点,这是一个伏笔。

好了,接着上面的式子 T r e n o T_{reno} Treno继续。

看到这样的式子,你想干什么,我看到这种四则单项的次幂格式,总想两边取对数。 这种式子是典型的双对数直线方程!

在取对数之前,我们先把表达式变成一个函数,因此将大写的 W W W P P P换成小写,表示通用的变量,同时我们接下来以固定RTT讨论,把RTT乘到左边,我们知道 T × R T T T\times RTT T×RTT就是窗口,这就少了一个控制变量,等到需要时我们再将RTT剥离回来即可:
w r e n o = T r e n o × R T T = 1.22 p − 1 2 w_{reno}=T_{reno}\times RTT=1.22p^{-\frac{1}{2}} wreno=Treno×RTT=1.22p21

那么好,两边取对数:

l o g ( w r e n o ) = l o g ( 1.22 ) − 1 2 l o g ( p ) log(w_{reno})=log(1.22)-\dfrac{1}{2}log(p) log(wreno)=log(1.22)21log(p)

这是一条在双对数坐标系里以$-\dfrac{1}{2}为斜率的直线。
在这里插入图片描述

和AIMD的cwnd-time图相比,这个双对数坐标换了一个视角,复杂的东西消失了,留下了直线。

RTT一定的情况下,这个直线方程 明确消除了AIMD行为的锯齿抖动带来的难计算性,它明确表达了丢包率和平均窗口或者说吞吐率的关系

拨云见日,柳暗花明,换一个视角,埋在下面的东西就浮到了表面。

就像看到单项次幂的表达式就像取对数一样,看到直线你想干什么?旋转,平移?…

从上图可以看出,吞吐率随着丢包率的降低而增加,问题是如果要保持一定的吞吐率,能容忍多大的丢包率呢?显然在这个角度来看,Reno的可扩展性不太好:

  • 为了保持高吞吐率,只能容忍极低的丢包率,而这在现实中很难保证。

把这个直线拉陡一点似乎可以解决问题,但是我们知道,这个直线方程是从 固定参数的AIMD算法 推导出来的,其斜率 − 1 2 -\dfrac{1}{2} 21是AIMD固有的,能改变的只有其参数 a a a b b b这些,也就是说无论 a a a b b b取什么值,也只是平移直线的效果,无法改变其斜率。显然,如果想让直线的斜率改变,参数便不能是固定的,更广义的AIMD算法描述如下:

  • AI过程:拥塞避免阶段每一个RTT增加 a = f ( w ) a=f(w) a=f(w)个窗口。
  • MD过程:遭遇丢包时,窗口减少原来的 b = g ( w ) b=g(w) b=g(w),即减少到 ( 1 − g ( w ) ) W (1-g(w))W (1g(w))W

基于这种进一步的抽象,把斜率也抽象成变量,我们把 T = 1 R T T a ( 2 − b ) 2 b 1 P T=\dfrac{1}{RTT}\sqrt{\dfrac{a(2-b)}{2b}}\dfrac{1}{\sqrt{P}} T=RTT12ba(2b) P 1抽象成下面的形式:
T = 1 R T T c P d T=\dfrac{1}{RTT}\dfrac{c}{P^d} T=RTT1Pdc

在RTT一定的情况下,将其方程化(将大写的名称变成小写的变量而已):

T × R T T = w = c p d = c p − d T\times RTT=w=\dfrac{c}{p^d}=cp^{-d} T×RTT=w=pdc=cpd

这就是所谓的 AIMD的response function !这个概念极其重要!!!

现在的问题转化成了两个子问题:

  • c c c d d d的值,得到一条新的p-w直线 L L L,使该直线更加陡一些。
  • 基于直线 L L L的表达式求 f ( w ) f(w) f(w) g ( w ) g(w) g(w)的表达式。

这就是High Speed TCP(HSTCP)的前传,接下来的故事全在其paper里了, Modifying TCP’s Congestion Control for High Speeds ,链接如下:
https://www.icir.org/floyd/papers/hstcp.pdf

paper有时很难啃,所以我这里还是要简要推导一下。

p-w双对数坐标上依然是两点可以确定一条直线,设两点分别为 ( P , W ) (P,W) (P,W) ( P 1 , W 1 ) (P_1,W_1) (P1,W1),其斜率显然就是:

S = l o g ( W 1 ) − l o g ( W ) l o g ( P 1 ) − l o g ( P ) S=\dfrac{log(W_1)-log(W)}{log(P_1)-log(P)} S=log(P1)log(P)log(W1)log(W)

按照点斜式方程,HSTCP的response function在双对数坐标下可以写成:
l o g ( w ) = S ( l o g ( p ) − l o g ( P ) ) + l o g ( W ) log(w)=S(log(p)-log(P))+log(W) log(w)=S(log(p)log(P))+log(W)

S S S的值代入两个点的坐标值很容易求出:

S = 0.82 S=0.82 S=0.82

按照对数的运算法则,方程可以化简为:

w = ( 1 P ) 0.82 W × p 0.82 w=(\dfrac{1}{P})^{0.82}W\times p^{0.82} w=(P1)0.82W×p0.82

P P P W W W分别代入,可得:

w = 0.15 p 0.82 w=\dfrac{0.15}{p^{0.82}} w=p0.820.15

OK,这就是HSTCP的response function了,下面如何来求其AI函数 f ( w ) f(w) f(w)和MD函数 g ( w ) g(w) g(w)呢?

需要注意的是,HSTCP依然是一个AIMD算法,它并没有破坏AIMD的原则。如果我们把 a = 1 a=1 a=1 b = 0.5 b=0.5 b=0.5的Reno的response function在双对数坐标的直线作为模版,在其上方画 n n n条与之平行的直线的话,HSTCP的想法就是,根据当前的 w w w窗口值,使用不同的这些与Reno直线平行的直线,事实上,HSTCP的response function在双对数坐标的直线确实穿过了所有这些直线:
在这里插入图片描述

因此,我们只需要两个点就能得到 f ( w ) f(w) f(w) g ( w ) g(w) g(w)的表达式,设已知点坐标 ( P , W ) (P,W) (P,W),代入标准Reno的response function:
W = f ( w ) ( 2 − g ( w ) ) 2 g ( w ) W W=\dfrac{\sqrt{\dfrac{f(w)(2-g(w))}{2g(w)}}}{\sqrt{W}} W=W 2g(w)f(w)(2g(w))

如果 ( P , W ) (P,W) (P,W)等于HSTCP在100ms RTT/10G带宽时的期望点,即 ( 1 0 − 7 , 83000 ) (10^{-7},83000) (107,83000),这意味着在100ms RTT时,达到10G带宽可以容忍 1 0 − 7 10^{-7} 107的丢包率,此时我们希望MD减窗操作仅仅减去 0.1 0.1 0.1的窗口,即 g ( w = 83000 ) = 0.1 g(w=83000)=0.1 g(w=83000)=0.1,代入上面的式子可以求得 f ( w = 83000 ) = 72 f(w=83000)=72 f(w=83000)=72

0.1 0.1 0.1是怎么来的呢?经验值吧。也可以是是 0.2 0.2 0.2

至此,结论就是, HSTCP从标准Reno的MD系数从常数0.5开始,需要在双对数坐标系里逐步地将其MD系数线性地降低到0.1!

线性降低 约束下求 g ( w ) g(w) g(w) f ( w ) f(w) f(w)就很容易了。

g ( w ) g(w) g(w)若想保持线性,其斜率可以参考 w ( p ) w(p) w(p)的反函数 p ( w ) p(w) p(w)计算:

S ′ = 1 S S^{'}=\dfrac{1}{S} S=S1

g ( w ) g(w) g(w) p ( w ) p(w) p(w)一样,保持 g ( w ) g(w) g(w) l o g ( w ) log(w) log(w)线性关系即可,两点式代入,得到 g ( w ) g(w) g(w)的方程:

g ( w ) − 0.5 l o g ( w ) − l o g ( W ) = 0.1 − 0.5 l o g ( W 1 ) − l o g ( W ) \dfrac{g(w)-0.5}{log(w)-log(W)}=\dfrac{0.1-0.5}{log(W_1)-log(W)} log(w)log(W)g(w)0.5=log(W1)log(W)0.10.5

由于 ( P , W ) (P,W) (P,W) ( P 1 , W 1 ) (P_1,W_1) (P1,W1)均是固定常量,因此很容易求出了 g ( w ) g(w) g(w)的表达式:

g ( w ) = − 0.4 l o g ( w ) − l o g ( W ) l o g ( W 1 ) − l o g ( W ) + 0.5 g(w)=-0.4\dfrac{log(w)-log(W)}{log(W_1)-log(W)}+0.5 g(w)=0.4log(W1)log(W)log(w)log(W)+0.5

最终,根据AIMD的response function就可以求出AI函数 f ( w ) f(w) f(w)了,其中AIMD的response function为:

w = f ( w ) ( 2 − g ( w ) ) 2 g ( w ) p w=\dfrac{\sqrt{\dfrac{f(w)(2-g(w))}{2g(w)}}}{\sqrt{p}} w=p 2g(w)f(w)(2g(w))

解出 f ( w ) f(w) f(w)即可。

现在有了 f ( w ) f(w) f(w) g ( w ) g(w) g(w)的表达式,可以考虑实现了。具体实现在RFC3649中描述的非常清楚:

https://tools.ietf.org/html/rfc3649

也可以看Linux内核代码 net/ipv4/tcp_highspeed.c

简单说一下下面这个表是怎么来的:

static const struct hstcp_aimd_val {
	unsigned int cwnd;
	unsigned int md;
} hstcp_aimd_vals[] = {
	{     38,  128, /*  0.50 */ },
	{    118,  112, /*  0.44 */ },
	{    221,  104, /*  0.41 */ },
	{    347,   98, /*  0.38 */ },
	{    495,   93, /*  0.37 */ },
	{    663,   89, /*  0.35 */ },
	{    851,   86, /*  0.34 */ },
	{   1058,   83, /*  0.33 */ },
	{   1284,   81, /*  0.32 */ },
	{   1529,   78, /*  0.31 */ },
	{   1793,   76, /*  0.30 */ },
	{   2076,   74, /*  0.29 */ },
	{   2378,   72, /*  0.28 */ },
	...

RFC3649附录B有详细的解法,我将代码中的aw,bw改成了fw,gw而已,以对应文中的AI函数 f ( w ) f(w) f(w)和MD函数 g ( w ) g(w) g(w)

$top = 100000;
$num = 38;
if ($num == 38) {
	print "     w  a(w)  b(w)\n";
	print "  ----  ----  ----\n";
	print "    38     1  0.50\n";
	$oldb = 0.50;
	$olda = 1;
}
# 1. 初始的窗口是38,它就在Reno线上,其AI参数为1。
# 2. HSTCP选择83000为最大窗口,0.1为此时的MD参数,经计算此时的AI参数为72。
# 3. HSTCP将从38到83000区间划分成72个小段,使得AI参数在每个小段递增1,此时正好可以用每段的索引下标表示AI参数。
while ($num < $top) {
	$gw = (0.1 -0.5)*(log($num)-log(38))/(log(83000)-log(38))+0.5;
	$fw = ($num**2*2.0*$gw) / ((2.0-$gw)*$num**1.2*12.8);
	# 每一段的AI参数递增1(这个是如何保证的呢?理论上如何保证fw是增函数呢?)
	if ($fw > $olda + 1) {
		printf "%6d %5d  %3.2f0, $num, $fw, $gw;
		$olda = $fw;
	}
	$num ++;
}

其中 "$num**1.212.8"* 的来历,参见:

w = 0.15 p 0.82 = > w 1.22 = 0.1 5 1.22 p w=\dfrac{0.15}{p^{0.82}} =>w^{1.22}=\dfrac{0.15^{1.22}}{p} w=p0.820.15=>w1.22=p0.151.22

这就是HSTCP全部的故事,下面我们来看一下它的公平性如何。

事实上,从AIMD的response function可以看出任何事情,包括吞吐效率,包括可扩展性,也包括公平性。

当我们谈到公平性的时候,我们主要侧重两个方面:

  • 非Reno算法对Reno算法的公平性,在CC大爆发的今天,实际上用CUBIC替代Reno。
  • 同一个算法内部的RTT公平性。

来看一下response function在双对数坐标的图形:
在这里插入图片描述

之所以会出现这么多的CC算法,根本原因还是Reno的不可扩展性,那么到底什么是可扩展性呢?

由于是大跨度按比例的对数关系,我们说response function直线(还真不一定必须是直线)越陡峭,可扩展性就越好,所谓的可扩展性说的就是 一定范围的丢包率可以适应更宽范围的吞吐 。那是不是就是说为了增加可扩展性,越陡的直线代表的response function对应的CC算法越好呢?我们还是简单算一下的好。

根据上面response function的定义,我们假定同一个算法的两个不同RTT流的RTT分别为 R T T 1 RTT_1 RTT1 R T T 2 RTT_2 RTT2,理想情况,虽然丢包率仅与buffer大小相关,与RTT无关,但对于每一个流而言,丢包率则是主观的,按照这个主观的定义,设丢包率分别为 p 1 p_1 p1 p 2 p_2 p2

全局意义上,两次丢包之间的时间是一个对所有流都一致的值,即buffer填满所需的时间,设为 t t t,那么,我们按照拥塞窗口的原始定义,两个流在两次丢包间隔时间 t t t内所发送的数据量分别为 1 p 1 \dfrac{1}{p_1} p11 1 p 2 \dfrac{1}{p_2} p21,那么两个流的平均拥塞窗口分别为:

w 1 = 1 p 1 t R T T 1 = R T T 1 t p 1 w_1=\dfrac{\frac{1}{p_1}}{\frac{t}{RTT_1}}=\dfrac{RTT_1}{tp_1} w1=RTT1tp11=tp1RTT1

w 2 = 1 p 2 t R T T 2 = R T T 2 t p 2 w_2=\dfrac{\frac{1}{p_2}}{\frac{t}{RTT_2}}=\dfrac{RTT_2}{tp_2} w2=RTT2tp21=tp2RTT2

然后,我们按照response function反算 p p p,首先给出 w 1 w_1 w1 w 2 w_2 w2

w 1 = c p 1 d w_1=\dfrac{c}{p_1^d} w1=p1dc

w 2 = c p 2 d w_2=\dfrac{c}{p_2^d} w2=p2dc

很容易解出 p 1 p_1 p1 p 2 p_2 p2

p 1 = ( c w 1 ) 1 d p_1=(\dfrac{c}{w_1})^{\frac{1}{d}} p1=(w1c)d1

p 2 = ( c w 2 ) 1 d p_2=(\dfrac{c}{w_2})^{\frac{1}{d}} p2=(w2c)d1

p 1 p_1 p1 p 2 p_2 p2分别带入原始定义的 w 1 w_1 w1 w 2 w_2 w2,可得:

w 1 = ( R T T 1 t c 1 d ) 1 d − 1 w_1=(\dfrac{RTT_1}{tc^{\frac{1}{d}}})^{\frac{1}{d-1}} w1=(tcd1RTT1)d11

w 2 = ( R T T 2 t c 1 d ) 1 d − 1 w_2=(\dfrac{RTT_2}{tc^{\frac{1}{d}}})^{\frac{1}{d-1}} w2=(tcd1RTT2)d11

现在可以计算两个流的吞吐之比了:

r 1 r 2 = w 1 R T T 1 w 2 R T T 2 = ( R T T 2 R T T 1 ) 1 1 − d \dfrac{r_1}{r_2}=\dfrac{\dfrac{w_1}{RTT_1}}{\dfrac{w_2}{RTT_2}}=(\dfrac{RTT2}{RTT_1})^{\frac{1}{1-d}} r2r1=RTT2w2RTT1w1=(RTT1RTT2)1d1

由此可见, d d d越大,越放大RTT差别对吞吐的影响,换句话说就是 d d d越大,RTT不公平性越明显, d d d越大意味着什么?意味着其双对数坐标的直线越陡呗!

看来确实,公平性和扩展性是互斥的,扩展性可以理解为平均效率,这就印证了 "效率和公平不可得兼!" 这句名言。

有了这个基础,对Reno的公平性就好理解了,不要过早越过Reno的response function的直线,也就是不要在丢包率很高的时候过早压制它。

关于公平性和可扩展性,总结如下:

  • response function在双对数坐标系越陡峭的直线,扩展性越好,RTT公平性越糟糕。
  • response function在双对数坐标和标准Reno的对应直线越晚相交,Reno公平性越好。
  • 鉴于上述二者不可得兼,最好就是双斜率/多斜率折线。

回头再看response function的一般形式:

w = c p d = c p − d w=\dfrac{c}{p^d}=cp^{-d} w=pdc=cpd

对于固定参数的AIMD算法而言,它就是:

w = ( a ( 2 − b ) 2 b ) 1 2 p − 1 2 w=(\dfrac{a(2-b)}{2b})^{\frac{1}{2}}p^{-\frac{1}{2}} w=(2ba(2b))21p21

其中它在通用格式方程中的 d d d是固定的 − 1 2 -\dfrac{1}{2} 21,而 c c c则是一个取决于 a a a b b b的变量 ( a ( 2 − b ) 2 b ) 1 2 (\dfrac{a(2-b)}{2b})^{\frac{1}{2}} (2ba(2b))21,从双对数坐标看得出来,平行于Reno直线的其它执行约往上,其 c c c值越大,这个时候,对于特定的一条或者几条平行线,我们可以得到 c c c的范围,如果再固定 b b b的范围,解一个不等式就能确定 a a a的范围,或者反过来从 a a a的范围求 b b b的范围。这为HSTCP的实现提供了可行性依据,RFC3649附录B的那个表的存在,也是依托于此。

如果同样是标准AIMD算法,只是AI参数 a a a和MD参数 b b b区别于Reno对应的 1 1 1 0.5 0.5 0.5,会怎样呢?简单情况下,假设相同的RTT,response function通用形式表示的二者吞吐之比为:

p ( a , b ) p ( 1 , 0.5 ) = ( a ( 2 − b ) 2 b 1.5 ) 1 2 \dfrac{p_{(a,b)}}{p_{(1,0.5)}}=(\dfrac{{\dfrac{a(2-b)}{2b}}}{1.5})^{\frac{1}{2}} p(1,0.5)p(a,b)=(1.52ba(2b))21

自己算吧,精选 a a a b b b,可以让你用自己的方式蹂躏Reno。在不同RTT情况下,依照和上面HSTCP RTT公平性类似的分析方法,也可以得到结论,这里就不赘述了。

回到最初,到底Reno出了什么问题,以至于HSTCP被设计出来来解决这个问题。

答案是,Reno很难适应长肥管道的高带宽和长延时,窗口打开慢。HSTCP的要旨在于 通过修改response function来适应高带宽网络, 损失一些公平性换取高带宽网络的可扩展性。

附两篇不易找到的文章,结束HSTCP的讨论:
http://www.hep.ucl.ac.uk/~ytl/tcpip/highspeedtcp/hstcp/background.htm
http://www.hep.ucl.ac.uk/~ytl/tcpip/highspeedtcp/hstcp/drafthighspeedtcp00.html

那么能不能在保证可扩展性的前提下, 用别的方式(显然在AIMD的框架内这是不可能的) 弥补公平性的损失呢?

办法当然有。

Vegas是一个与AIMD完全不同的AIAD算法,为HSTCP引入Vegas-like的特征消除不必要的激进。

这就是 TCP-Africa 。和Reno,Vegas,Westwood不同,Africa这回不是地名了,而是 Adaptive and Fair Rapid Increase Congestion Avoidance 首字母的缩写。

TCP Africa引入了一个常数 α \alpha α,即排队数据包量,它的计算很容易理解,设 a R T T aRTT aRTT为实际测算的RTT, m i n R T T minRTT minRTT为无排队时的RTT, W W W为当前窗口,那么下面的式子表示排队的数据包数量:

Q = W ( a R T T − m i n R T T ) a R T T Q=\dfrac{W(aRTT-minRTT)}{aRTT} Q=aRTTW(aRTTminRTT)

如果 Q Q Q大于常数 α \alpha α,那么显然在旁观者看来,排队已经足够严重,这意味着丢包总会来临,此时激进增窗是损人不利己的毫无意义的行为,因此退回到Reno,否则就使用HSTCP的AI过程,所以,TCP Africa的算法就是:

if (Q < alpha) {
	W = W + f(W)/W; // HSTCP Additive Increase
} else {
	W = W + 1/W; // Reno Additive Increase
}

我相信很多人看到这个算法之后都有一种把else分支去掉的冲动,显然这些人并不知道TCP Africa的来龙去脉,如果去掉了else分支,那不就是HSTCP了吗?之所以增加else分支,就是因为HSTCP是不公平的。

下面的链接里有关于TCP Africa的说明:
https://cglab.ca/~dana/tcpafrica/

High capacity data transfers over the Internet routinely fail to meet end-to-end performance expectations. The default transport control protocol for best effort data traffic is currently TCP, which does not scale well to 100Mbps and higher networks over long distances. In congestion avoidance TCP is not swift enough to fully utilize resources over paths with a high delay bandwidth product. First attempts to alleviate this problem by equipping TCP with increased aggressiveness have shown the disadvantage of poor fairness with the ubiquitous standard TCP-Reno, or in some cases, even among two connections running over the same path. We propose a new delay sensitive congestion avoidance mode (TCP-Africa) that allows for scalable, aggressive behavior in large underutilized links, yet falls back to the more conservative TCP-Reno algorithm once links become well utilized and congestion is imminent. Through ns2 simulations we argue for the safety, efficiency, and fairness of TCP-Africa.

看来,看似一个个Magic number是不知怎么调配而成的经验值,其实背后有一套严密的数学论证,换句话说,它们是精心算出来的。它们不会给你 调的一手好参数 的空间。那么,区分什么参数是算出来的,什么参数是可以随意调整的,就需要一种能力了。 我们所做的每一件事都需要理论依据作为支撑。

如果真的手痒,真的特别想调那个HSTCP的hstcp_aimd_vals数组,怎么办呢?很简单,按照response function的推导逻辑,重新来一遍,从最底层的方程式入手,选择你需要的那个斜率以满足你的扩展性要求,然后按照RFC3649附录B的算法重新计算,便得到了一个新的数组,这才是正道。

如果仅仅是看着数字小就要改大,看着数字大就要改小,搞什么快增窗,慢减窗策略,那就是纯粹扯淡!

比较有意思的是,有人把从TCP Africa到HSTCP的回退作为一种新的优化算法发布,并且取了一个新名字TCP China,起初我觉得这哥们儿有点自作聪明,显然这哥们儿是把TCP Africa理解成TCP非洲了,因为我实在想象不出China是哪些描述TCP性能的短语的首字母缩写。但看了作者的README之后,我发现也许他也是在反讽。

我们看看作者是怎么说的:

TCP-CHINA Congestion control algorithm, based on very few modifications to TCP-AFRICA.

Modifications are simple: Always keep using fast mode of TCP_AFRICA.

This is yet another demostration of how easily we can increase TCP sending speed from the server side if you ignore fairness and friendliness.

WARNING: DO NOT USE THIS MODULE!

我相信作者知道自己在做什么。

洋洋洒洒扯了这么多,有卵用吗?我觉得没卵用,这本来就是扯淡。但我也没魔改TCP啊是不是?


浙江温州皮鞋湿,下雨进水不会胖。

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值