带宽探测 · 主动试探能不能更快

光被动测量,涨得太慢——通话开始或网络变好时,得主动发探测包快速试探可用带宽。这一章读 goog_cc 的 ProbeController:探测怎么用成串的包测出瞬时吞吐、padding 与 RTX 两种探测手段,以及探测为什么能让码率快速爬坡。

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

带宽探测 · 主动试探能不能更快

延迟based的 AIMD 加性增很稳,但也很慢——小步慢涨,要好久才能爬到高带宽。通话刚开始(从零起步)或网络突然变好时,慢涨意味着画质半天上不来。所以 GoogCC 还有一招主动的:带宽探测(probing),由 goog_cc/probe_controller.h 的 ProbeController 负责。

思路:成串发包,看它们怎么到

探测 = 故意在短时间内发一串(cluster)包,看它们到达接收端时被“压”成什么样,从而直接测出瞬时可用带宽。 原理:如果你以 5 Mbps 的速率发一串包,而链路只有 3 Mbps,这串包会在瓶颈处排队、被拉开间隔——到达端一算它们的到达速率,就知道「实际只能跑 3 Mbps」。反之若它们几乎原速到达,说明链路至少有 5 Mbps,可以放心涨上去。

这比 AIMD 慢慢试快得多:AIMD 要很多个 RTT 一点点涨,探测一串包、一个来回就能测出「能不能到 5 Mbps」,让码率直接跳上去。代价是探测包本身占带宽(万一链路不够,这串包还加重了瞬时拥塞),所以要用得克制——只在该探测的时机探。

什么时候探测

ProbeController 决定何时发探测,典型时机:

  • 通话启动 —— 从一个初始猜测(如 300 kbps)快速爬坡到真实带宽。没有探测,新通话的画质要好几秒才能起来;有探测,一两秒就能冲上去。
  • 码率被降后网络恢复 —— 之前因拥塞降了码率,现在延迟 / 丢包都好转,探测一下「是不是能涨回去了」,避免长期被压在低码率。
  • 达到当前估计上限 —— AIMD 已经涨到当前估计的天花板,探测「天花板之上还有没有空间」。

探测包哪来:padding 与 RTX

探测要发「额外的包」,这些包哪来?PT 分配那章提过,g3doc/rtp.md 讲了两种手段:

手段是什么特点
padding 包纯 RTP 填充(无媒体)收端直接丢弃;但单包 payload ≤256 字节,要发很多包
RTX 包重发历史里未确认的旧包更优:万一那包真丢了还兼做冗余,不纯浪费

g3doc/rtp.md 明说 RTX 探测优于 padding 探测。 因为 padding 包纯属浪费(收端丢弃),且单包填充上限 256 字节,要凑够探测流量得发一大堆小包——从拥塞控制角度看,包数太多不理想。而 RTX 探测重发的是真实的旧媒体包:它们既完成了探测,万一对应的原包真丢了,这次重发还顺便修复了丢包——一举两得,不浪费。所以优先用 RTX 探测,只在 RTX 没协商(如纯音频)或找不到合适的旧包时,才退回 padding。连“浪费在探测上的带宽”都想办法让它有用——这种精打细算,是成熟实时系统的特征。

探测让码率快速爬坡

有了探测,码率曲线的形状就好看多了:

图表加载中…

探测负责“快速跳到大致水平”,AIMD 负责“精细微调”——一个粗调快、一个细调稳,配合起来,码率既能快速起来、又能稳定收敛。这是 GoogCC 用户体验好的一大原因:视频通话接通没几秒画质就清晰了,靠的正是探测的快速爬坡。

小结与下一章

带宽探测主动发一串包、测它们的到达速率,直接测出瞬时可用带宽——比 AIMD 慢涨快得多。ProbeController 在通话启动、码率恢复、触及上限等时机探测。探测包用 padding(浪费、量大)或 RTX(重发旧包,兼修丢包,更优)。探测快速跳档 + AIMD 精细微调,让码率又快又稳地贴住网络容量。

估计出了目标码率,但包不能一股脑猛发——那会造成瞬时拥塞。得平滑地、按节奏吐出去,这是 pacing 的活。下一章。👉 Pacing 平滑发包。

参考资料

  • [1] libwebrtc 源码.modules/congestion_controller/goog_cc/probe_controller.h、probe_bitrate_estimator.h。
  • [2] libwebrtc 源码.g3doc/rtp.md(padding / RTX 探测对比)。
  • [3] IETF「GoogCC」draft —— probing 部分。

本页目录