丢包based 带宽估计 · 兜底的另一只眼

延迟based 有盲区,丢包based 作为另一只眼补上。这一章读 goog_cc 的 LossBasedBweV2:它怎么用丢包率估带宽、为什么和延迟based 取小、以及从早期简单丢包阈值到 v2 的演进——把丢包信号用得更精细。

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

丢包based 带宽估计 · 兜底的另一只眼

延迟based 是主控,但它并非全知。有些网络场景它会失灵,这时需要另一只眼——丢包based 带宽估计。它是 GoogCC 双控制器的另一半,goog_cc/loss_based_bwe_v2.h 里的 LossBasedBweV2。

为什么还需要看丢包

延迟based已经很灵敏了,为什么不够?

延迟based 假设「拥塞 → 排队 → 延迟涨」,但有些网络不排队就直接丢包,延迟信号会失灵。 典型:

  • 浅缓冲 / 主动丢包的链路 —— 有些路由器缓冲区极小,或用 AQM(主动队列管理)在排队变长前就丢包。这时延迟涨得不明显,延迟based嗅不到,但丢包率已经上来了。
  • 无线链路的随机丢包 —— Wi-Fi / 蜂窝有本底的随机丢包(信号干扰),和拥塞无关。这又是反过来:丢包不一定意味着拥塞。

所以丢包是另一个维度的信号,和延迟互补:延迟看「排队」,丢包看「溢出 / 损耗」。两者结合,覆盖面才全。这也是为什么 GoogCC 要跑两个控制器并取小——任一控制器说「该降」,就降,谁也别漏报拥塞。

丢包信号怎么用:从简单阈值到 v2

丢包based 估计的演进,是把「丢包」这个信号用得越来越精细:

  • 早期(简单阈值) —— 一套朴素规则:丢包率低于某阈值(如 2%)→ 可以涨;高于某阈值(如 10%)→ 降;中间 → 保持。直接、但粗糙——它没充分利用「丢多少、和码率什么关系」。
  • LossBasedBweV2(现代) —— 更精细的模型。它综合丢包率、当前码率、已确认的吞吐 等,用一个更完整的方法估出「在当前丢包水平下,可持续的带宽是多少」,而非简单的「过阈值就降」。它的入口是 UpdateBandwidthEstimate,吃一批 PacketResult(每个包丢没丢):
// goog_cc/loss_based_bwe_v2.h(节选)
class LossBasedBweV2 {
  void UpdateBandwidthEstimate(std::span<const PacketResult> packet_results, ...);
};

v2 又是 WebRTC「带版本号的现代重写」。 从简单丢包阈值到 LossBasedBweV2,反映了拥塞控制的持续打磨:同样是「看丢包」,v2 把丢包信号和码率、吞吐联系起来,估得更准、和延迟based 配合得更好——尤其在延迟信号不可靠的网络里,它扛起了主要判断。读到 goog_cc 里各种 v2/v3,都是这种「同一信号,越用越精」的迭代痕迹。带宽估计是个永远在优化的领域,因为真实网络的花样是无穷的。

取小:谁保守听谁

总览说过,GoogCC 取延迟based 和丢包based 的较小值作为最终估计。再强调一次这个设计的稳妥:

  • 延迟based 说 3 Mbps、丢包based 说 5 Mbps → 用 3 Mbps(延迟已预警,别冒进)。
  • 延迟based 说 5 Mbps、丢包based 说 2 Mbps → 用 2 Mbps(丢包已很多,必须降)。

任一信号预警,就采纳更保守的那个。 拥塞控制里,「宁可保守、不可冒进」是安全的默认——因为冒进的代价(卡顿)远大于保守的代价(画质略降)。两只眼睛,一个看排队、一个看损耗,取更警觉的那个,GoogCC 才能在五花八门的真实网络里都不翻车。

小结与下一章

丢包based 估计是延迟based的互补兜底:有些网络不排队就丢包(浅缓冲、AQM)或有随机丢包(无线),延迟信号失灵,得靠丢包率。现代 LossBasedBweV2(UpdateBandwidthEstimate 吃 PacketResult)比早期简单阈值更精细,综合丢包率、码率、吞吐估带宽。GoogCC 取延迟 / 丢包两估计的较小值——任一预警就保守。

估计是「被动」测量,但 GoogCC 也会主动出击——发探测包试探「能不能更快」。下一章讲带宽探测。👉 带宽探测。

参考资料

  • [1] libwebrtc 源码.modules/congestion_controller/goog_cc/loss_based_bwe_v2.h / .cc(UpdateBandwidthEstimate)。
  • [2] libwebrtc 源码.goog_cc/send_side_bandwidth_estimation.h(早期丢包逻辑)。
  • [3] IETF「GoogCC」draft —— 丢包based 部分。

本页目录