TCP BBR的startup bbr_high_gain为什么是2/ln2?
温州皮鞋厂老板上周就一直在问这个。正好昨天和今天早上有空,加上又在雨夜,就写一波。
温州皮鞋厂老板的问题如下:
慢启动:
增长速率为 求导=. pacing_gain应该等于类似这个东西来算吧
怎么就了
其实一开始我也不知道,根本就没有注意过这个问题,能找到的资料也就是tcp_bbr.c中关于bbr_high_gain的注释:
/* We use a high_gain value of 2/ln(2) because it's the smallest pacing gain
* that will allow a smoothly increasing pacing rate that will double each RTT
* and send the same number of packets per RTT that an un-paced, slow-starting
* Reno or CUBIC flow would:
*/
static const int bbr_high_gain = BBR_UNIT * 2885 / 1000 + 1;
另外,BBR的paper:
https://queue.acm.org/detail.cfm?id=3022184
这里面也能找到一段论述:
To handle Internet link bandwidths spanning 12 orders of magnitude, Startup implements a binary search for BtlBw by using a gain of 2/ln2 to double the sending rate while delivery rate is increasing. This discovers BtlBw in log2BDP RTTs but creates up to 2BDP excess queue in the process.
除此之外,就再也找不到别的资料了。我自己也很好奇,也跟很多人进行了讨论,甚至包括BBR的作者之一Neal Cardwell,最终以我自己的理解,整理出了这篇文章,希望能帮同样有此疑问的人解惑。
在Startup阶段,BBR的bbr_high_gain同时作用于和两者,两者遵循同样的演化规律,即随着轮数而指数级递增:
因此,在推导bbr_high_gain时,可以沿着两条路分别进行,我们先沿着积分到这条路推导出视角的bbr_high_gain,然后再通过求导到这条路来验算。
假设在第个时其是,那么在下一个,即个时,它的就会变成,多了个,在Startup阶段,也遵循同样的演化规律。
为了推导简单,我们将设,,均为来归一化,同时用自变量表示以一个为单位的轮数,上面的式子可以写成:
而我们知道,是在时间上的积分(忽略常数C)。根据我们的假设,我们是按轮数来计数的,所以一个单位内的就是一个关于的定积分:
按照牛顿-莱布尼兹定理则有:
抽掉中的时间维度,在数值上它的意义就是。
设为增益系数,根据间隔一个时其的关系,则有:
化简可以得到:
所以,我们就得到了:
接下来,我们来沿着从到这条路来再走一遍,看看求出的增益系数是不是同一个值。
我们知道,发送量的变化率其实就是发送速率,因此对关于时间求导,就可以得到速率:
设为的增益系数,则有:
经过演化的恰好就是的数值:
所以,我们可以求出的数值:
可以看出,这里的的增益和前面的增益在数值上是完全一致的,这也就是TCP BBR中的那个魔数的由来。
如果你足够细心,你会发现上面的推导中有一个破绽。比如,既然,而又由求导产生,和均表示时,显然而然的是:
!!
其实,函数和之所以这么写是因为它们在离散的上表现得确实如此,但在实际中,速率计算,计算并非总是由平滑均匀的ACK事件来触发的,所以说就必须用一条光滑的曲线来尽量拟合离散的点,因此,上面的,本身就不是光滑曲线,它们和本身就不是同一条曲线。
实际上,和表示的均是折线,所要做的正是用光滑的曲线去拟合折线上那些离散的转折点,所以说,只能用增益系数代入去解方程,而不是直接让两个函数相等。
和的图像类似下面这样:
我们再把代表的平滑拟合曲线以及代表的平滑拟合曲线画到同一个坐标系中:
可以看得出,它们是3样不同的曲线。
不过,看起来和对离散的和拟合得并不是很理想,那为什么不直接用来拟合呢?它可是能完美拟合的吧:
或者,我们可以用二项式去拟合,用级数…
然而这些都不行。为什么呢?因为要考虑到计算,这里并不是在解一道数学题,而是要求出一个确定的常数作为增益系数,注意,是确定的常数。如果不通过积分或者求导的方式引入一个因子,单纯的是无法得到一个确定的常数的。
这种方法,我们感到似曾相识,TCP的拥塞控制算法,从BIC到CUBIC就是采用了这种光滑的三次曲线拟合BIC二分折线的方法,其中的那些参数也可以用类似的方法求解。
除此之外,以上推导中,下面的关系是不存在的:
为什么?因为和上的点是离散的,非连续函数在无定义的域上求值没有意义。然而ACK的到达并非以RTT为单位准点的,更有可能遭遇ACK丢失,ACK聚集等无法预知的时间,因此ACK到达是任意的,所以就必须用光滑的曲线来拟合这些离散的点,从而达到比较平滑的增益效果。
简单点说,增益系数的结果是针对光滑的拟合曲线而言的,即针对以及的,而不是针对和的。