延迟based 带宽估计 · trendline 与过载检测

GoogCC 的主控制器,靠「延迟趋势」在丢包前就嗅到拥塞。这一章读 goog_cc 的 DelayBasedBwe 与 TrendlineEstimator:怎么从包的到达时间算出延迟变化、用线性回归判断趋势、over-use detector 如何输出 kNormal/kOveruse/kUnderusing,以及 AIMD 如何据此加减码率。

作者 David更新于 第 45 篇(共 112 篇)

延迟based 带宽估计 · trendline 与过载检测

GoogCC 的主控制器是延迟based 的。它有个了不起的本事:在丢包真正发生之前,就从延迟的细微变化里嗅到拥塞将至。 这一章拆解它怎么做到——DelayBasedBwe 与它的核心 TrendlineEstimator。

核心信号:延迟在涨吗

原理起点很直觉:

网络快堵时,最早的征兆是「延迟开始涨」——因为路由器的缓冲区开始排队。 想象一条路快堵车了:车还没完全停(还没丢包),但每辆车通过的时间变长了(排队)。网络也一样:你发得比链路容量快时,超出的包在路由器缓冲区排队,于是它们的传输延迟逐渐增大——这比「缓冲区满了开始丢包」早得多。所以盯住「延迟趋势」,就能提前发现拥塞。

数据从哪来?Transport-CC 反馈——它告诉发送端每个包何时发、何时到。比较「发送间隔」和「到达间隔」的差异,就得到延迟的变化:如果一组包的到达比发送越来越晚,延迟在涨,拥塞在逼近。

TrendlineEstimator:用回归看趋势

单看一两个包的延迟会有噪声(网络本就抖动)。要看趋势,TrendlineEstimator(goog_cc/trendline_estimator.h)用线性回归:

// goog_cc/trendline_estimator.h(节选)
class TrendlineEstimator : public DelayIncreaseDetectorInterface {
  BandwidthUsage State() const override;   // 当前判断:正常/过载/欠载
  BandwidthUsage hypothesis_;
};

它把最近一批包累积的延迟变化拟合成一条直线,看这条线的斜率(trend):斜率明显为正 = 延迟在稳定上升 = 拥塞;斜率约零 = 平稳;斜率为负 = 延迟在降(网络在疏通)。用回归而非单点,是为了从抖动的噪声里提取出真实趋势——这是信号处理的常规智慧。

过载检测:三种状态

趋势斜率和一个动态阈值比较,TrendlineEstimator 输出三种 BandwidthUsage 状态:

BandwidthUsage 三态,是延迟based 控制的判决:

  • kNormal(正常) —— 延迟趋势平稳,网络没堵,可以维持甚至试探提速。
  • kOveruse(过载) —— 延迟趋势明显上涨,发过量了,必须降码率。这是最关键的信号。
  • kUnderusing(欠载) —— 延迟在下降,说明之前降过头 / 网络刚疏通,可以恢复。

关键设计:那个判决阈值是动态自适应的——不是写死一个「延迟涨多少算过载」。因为不同网络的基础抖动差异极大(光纤 vs 4G),固定阈值要么太敏感(误报)、要么太迟钝(漏报)。动态阈值会根据观测到的延迟波动自我调整,在各种网络下都能恰当地区分「正常抖动」和「真的在过载」。这种自适应,是 GoogCC 鲁棒性的来源之一。

AIMD:加性增,乘性减

拿到过载检测的三态,怎么调码率?用经典的 AIMD(Additive Increase, Multiplicative Decrease,加性增、乘性减)——和 TCP 拥塞控制同源的思想:

  • kNormal → 加性增(小步慢涨) —— 没堵,就缓慢线性地试探性提高码率,一点点往上探,找网络的上限。
  • kOveruse → 乘性减(大步快降) —— 一过载,就成比例地大幅降码率(比如乘 0.85),快速让出拥塞。

为什么增要慢、减要快?这是拥塞控制的黄金法则,背后是「代价不对称」。 涨过头的代价(拥塞、延迟飙升、卡顿)远大于保守一点的代价(画质略低)。所以探测上限要谨慎(加性小步,万一涨过头损失有限)、发现过载要果断(乘性大步,快速脱离拥塞、把排队的延迟泄掉)。慢涨快降,让系统稳定地收敛到网络容量附近来回小幅摆动,而不会剧烈震荡。这个「慢涨快降」的智慧,几乎所有拥塞控制(TCP、QUIC、WebRTC)都遵循。WebRTC 里由 AimdRateControl 实现这套加减逻辑。

一张估计流程图

图表加载中…

小结与下一章

延迟based 估计在丢包前就嗅到拥塞:网络快堵时延迟先涨(缓冲区排队),靠 Transport-CC 算出延迟变化。TrendlineEstimator 用线性回归从噪声里提取趋势斜率,过载检测用动态阈值输出 BandwidthUsage 三态(kNormal/kOveruse/kUnderusing)。据此跑 AIMD:正常加性增(慢涨)、过载乘性减(快降)——慢涨快降因代价不对称,让码率稳定收敛。

延迟based 是主控,但它有盲区(比如链路本身随机丢包时)。丢包based 控制器作为兜底补上。下一章。👉 丢包based 带宽估计。

参考资料

  • [1] libwebrtc 源码.modules/congestion_controller/goog_cc/trendline_estimator.h、delay_based_bwe.h、aimd_rate_control.h。
  • [2] Holmer et al.「A Google Congestion Control Algorithm...」—— trendline 与 over-use detector。
  • [3] BandwidthUsage 枚举(api/transport/)。

本页目录