RateStatistics类位于rtc_base 目录下面,属于WebRtc 基础类之一。这个类主要功能是统计一段时间内的带宽的情况。由于很多地方用到这个带宽统计的功能,所以有很多地方调用到了RateStatistics。
RateStatistics 主要提供了四个公有函数:
void Reset();
void Update(size_t count, int64_t now_ms);
absl::optional Rate(int64_t now_ms)const;
bool SetWindowSize(int64_t window_size_ms, int64_t now_ms);
void RateStatistics::Reset() {
accumulated_count_ = 0;
num_samples_ = 0;
oldest_time_ = - max_window_size_ms_;
oldest_index_ = 0;
current_window_size_ms_ = max_window_size_ms_;
for(int64_t i =0; i < max_window_size_ms_; i++)
buckets_[i] = Bucket();
}
Reset函数就是各种参数重置了
voidRateStatistics::Update(size_t count, int64_t now_ms) {
if(now_ms < oldest_time_) {
return;
}
EraseOld(now_ms);
// First ever sample, reset window to start now.
if (!IsInitialized())
oldest_time_= now_ms;
uint32_t now_offset =static_cast(now_ms -oldest_time_);
RTC_DCHECK_LT(now_offset, max_window_size_ms_);
uint32_t index =oldest_index_+ now_offset;
if (index >= max_window_size_ms_)
index -=max_window_size_ms_;
buckets_[index].sum += count;
++buckets_[index].samples;
accumulated_count_ += count;
++num_samples_;
}
Update函数实际上在进行添加的操作。在添加之前先删除旧的数据,删除旧的数据EraseOld,实际上是按照一定的规则删除的,如果没有达到条件是不会删除任何数据。
用当前的值,减去最早的记录值得到一个偏移量,偏移量加上最早的序号,得到的值就是桶(buckets)的索引序号。oldest_time_ 和oldest_index_在这个函数中只是使用,这两个值都是在删除旧数据和重置的时候进行修改(第一次插入数据除外)。
absl::optional<uint32_t> RateStatistics::Rate(int64_t now_ms) const {
const_cast(this)->EraseOld(now_ms);
int64_t active_window_size = now_ms -oldest_time_+1;
if(num_samples_==0|| active_window_size <=1||
(num_samples_<=1&& active_window_size< current_window_size_ms_)) {
return absl::nullopt;
}
float scale =scale_/ active_window_size;
return static_cast(accumulated_count_* scale +0.5f);
}
这个函数就是获取带宽值了。这里有一个空值的返回,当桶里面只有一个数据的时候,或者没有达到最大的窗口大小直接返回一个空值。其他情况才是对根据当前的时间,获取一段时间内(max_window_size_ms_)带宽值。
void RateStatistics::EraseOld(int64_t now_ms) {
if (!IsInitialized())
return;
// New oldest time that is included in data set.
int64_t new_oldest_time = now_ms - current_window_size_ms_+1;
// New oldest time is older than the current one, no need to cull data.
if(new_oldest_time <=oldest_time_)
return;
// Loop over buckets and remove too old data points.
while(num_samples_>0&&oldest_time_< new_oldest_time) {
const Bucket& oldest_bucket = buckets_[oldest_index_];
RTC_DCHECK_GE(accumulated_count_, oldest_bucket.sum);
RTC_DCHECK_GE(num_samples_, oldest_bucket.samples);
accumulated_count_-= oldest_bucket.sum;
num_samples_-= oldest_bucket.samples;
buckets_[oldest_index_] = Bucket();
if (++oldest_index_ >= max_window_size_ms_)
oldest_index_ = 0;
++oldest_time_;
}
oldest_time_= new_oldest_time;
}
删除旧数据的函数。最早的数据oldest_time_小于 now_ms - current_window_size_ms_+1的时候才会触发,这时候一般情况下num_samples_会大于0。然后循环删除最久的数据。
bool RateStatistics::SetWindowSize(int64_t window_size_ms, int64_t now_ms) {
if(window_size_ms <=0 || window_size_ms >max_window_size_ms_)
return false;
current_window_size_ms_ = window_size_ms;
EraseOld(now_ms);
return true;
}
设置窗口大小的函数
bool RateStatistics::IsInitialized() const {
return oldest_time_ != -max_window_size_ms_;
}