速率统计 · RateStatistics 滑动窗口测速率
「当前码率是多少」这个问题在 WebRTC 里被问了无数次——pacer、带宽估计、统计报告都要。这一章读 rate_statistics.h,讲清 RateStatistics 这个滑动窗口速率估计器怎么工作,以及为什么「测速率」这么个小工具值得单独一个类。
速率统计 · RateStatistics 滑动窗口测速率
“现在发送码率多少?”“刚才收进来多少 kbps?”——这类问题在 WebRTC 里被问了无数次:pacer 要知道自己发多快、带宽估计要测进出码率、stats 要报告比特率。测速率听着简单,做对却有讲究,WebRTC 为它专设了一个类:RateStatistics。这是第 10 部分的最后一个零件。
“测速率”没那么简单
朴素做法:“总字节数 ÷ 总时间”。但这给的是从头到now的平均,对实时系统毫无用处——我们要的是“最近这一小段的速率”(比如最近 1 秒),它才反映当前网络 / 编码的真实状态。
实时系统要的是“瞬时”速率——最近一个滑动窗口**(如 1 秒)内的速率,而不是从开始到现在的累计平均。窗口要随时间滑动:新数据进来、老数据(超出窗口的)淘汰。** 为什么必须是滑动窗口?
- 反映当下 —— 码率一直在变(网络波动、画面复杂度变化),只有“最近一段”的速率对决策有意义。累计平均会被很久以前的数据拖累,反应迟钝。
- 要平滑 —— 但也不能只看最后一个包(太抖)。窗口是“既反映当下、又足够平滑”的折中,窗口越大越平滑但越迟钝,越小越灵敏但越抖。
- 要高效 —— 每来一个包就重算整段太慢,得增量维护。
RateStatistics 就是把这件“看似简单、细节不少”的事做对、并封装成可复用的一个类——整个 WebRTC 凡是要测速率的地方都用它,不必各自重造。
RateStatistics 的接口
看它的接口(真实源码 rate_statistics.h),很直观:
// rate_statistics.h(节选,真实源码)
class RateStatistics {
public:
// max_window_size_ms:窗口最大长度;scale:换算系数(如 8000 把 字节/ms 变 bps)
RateStatistics(int64_t max_window_size_ms, float scale);
void Update(int64_t count, int64_t now_ms); // 在 now_ms 时刻,新增 count(如字节数)
std::optional<int64_t> Rate(int64_t now_ms) const; // 取 now_ms 时刻的当前速率
bool SetWindowSize(int64_t window_size_ms, int64_t now_ms); // 动态调窗口
};用法就三步:每来一批数据 Update(字节数, 现在),想知道速率时 Rate(现在),需要更灵敏 / 更平滑时 SetWindowSize。内部维护一个按时间排列的桶结构,Update 往当前时刻的桶加计数、Rate 把窗口内所有桶求和再除以窗口时长乘 scale,并丢弃超出窗口的老桶——滑动就是这么实现的。
scale 参数是个贴心设计:它把“原始计数 / 毫秒”换算成你想要的单位。 传 count 为字节数、要 bps 结果时,scale = 8000(× 8 变 bit、× 1000 因为 ms→s)。这样 Rate() 直接返回 bps,调用方不用自己换算——又一次类型 / 单位上的体贴。返回 std::optional 是因为窗口内数据太少时速率无意义(测不准),此时返回空,提示调用方“还没法给出可靠估计”。
它在系统里无处不在
RateStatistics 是那种“不起眼但到处都在”的基础件:
一个小类,服务了码率传导链的多个环节。这正是 rtc_base 的价值:把反复出现的通用需求(“测最近一段的速率”)做对一次、到处复用。
小结与下一章
RateStatistics(rate_statistics.h)是 WebRTC 的滑动窗口速率估计器。它解决“测瞬时速率”这个实时系统的高频需求:不是从头到now的累计平均,而是最近一个窗口内的速率,窗口随时间滑动(新数据进、老数据淘汰)——在“反映当下”与“足够平滑”间折中。接口简单:Update(count, now) 加数据、Rate(now) 取速率、SetWindowSize 调灵敏度,scale 参数自动换算单位,数据太少时返回 optional 空值。它服务于 pacer、BWE、stats 等多处——通用件复用的典范。
第 10 部分的地基零件到此看完。下一章为这一部分收尾,并展望后面的观测与平台集成。👉 第 10 部分回顾。