同事咨询了一个有趣的问题,bbr 在probe bw 状态下,rtt 变小了,但采集到的 delivery date 却没变,此时算出来的 cwnd 变小,限制了 sender 发送。这种情况应该调什么参数。
这是 bbr 一个典型的循环依赖 bug,迟至 bbr3 才稍微解决,详见 bbrv3 fix 2。简单说,interval 变小,delivery rate = delivered / interval 本应变大,但由于 cwnd = interval * delivery rate * cwnd_gain 限制了 inflight,导致 delivered 也变小,就循环依赖。
简单推导一下原因。先看 bbr 最大可利用的 buffer。
max_inflight = cwnd_gain * probe_up_gain * delivery_rate * interval
将当前 bbr 参数配置代入上式:
max_inflight = 2 * 1.25 * delivery_rate * interval = 2.5 * BDP
因此:
max_buffer_used = max_inflight - BDP = 1.5 * BDP
这意味着超过 1.5 * BDP 的 buffer 是 bbr 无法利用(这其实是好事)的,在 deep buffer 和背景流共存时非常吃亏。另一方面,BDP = delivery_rate * interval,当 interval 变小时,BDP 变小,这直接进一步减少了 max_buffer_used 的上限,即使进入随后的 probe up 阶段,也无力突破这个由于 interval 减少而降低的上限,更别提 cruise 阶段直接削减 inflight 了。
bbr3 直接将 probe up 阶段的 cwnd_gain 改成了 2.25,bbr1 的改法如下:
case BBR_PROBE_BW:bbr->pacing_gain = (bbr->lt_use_bw ?BBR_UNIT :bbr_pacing_gain[bbr->cycle_idx]);// 我直接改成了 3,改成 2.5,2.25 都行bbr->cwnd_gain = bbr->pacing_gain > BBR_UNIT ? BBR_UNIT * 3 : bbr_cwnd_gain;break;
直接硬调还是粗暴了,万一遇到更 deep 的 buffer 呢,要进一步增加 cwnd_gain 吗?
大可不必为保持和 cubic 在 deep buffer 的公平性而有意伸展 cwnd_gain,否则就倾向于变成 cubic。2x 的 cwnd_gain 足用,保持不退缩即可。
设 delta_interval 为新老 interval 之差,则 delta_max_buffer_used = 1.5 * delivery_rate * delta_interval,保持该值为 0,算出 delta_cwnd_gain 即可,附加到用新的 cwnd_gain 进行 probe up,则始终保持 buffer 最大用量不超过 BDP 的一定比例。
保持 probe up 阶段的抢占性不因自身测量行为被削弱,而不是无条件放宽 inflight 限制而提高 buffer 最大用量,deep buffer 非标,不应作为算法假设,除非在实践中可体现,但不是算法本身。此外,提高 cwnd_gain 在 shallow buffer 下还会造成高丢包。
索性再粗暴一点,不要改代码,直接将 cwnd_gain 参数改成 3,调参即可,意思差不多,丢包多点儿,不过反正也不在乎,重传猛就行。
delivery_rate * (interval_prop + interval_queuing)
皮鞋没有蹬上,露着白袜子。
浙江温州皮鞋湿,下雨进水不会胖。