RateStatistics類位于rtc_base 目錄下面,屬于WebRtc 基礎(chǔ)類之一睡毒。這個(gè)類主要功能是統(tǒng)計(jì)一段時(shí)間內(nèi)的帶寬的情況来惧。由于很多地方用到這個(gè)帶寬統(tǒng)計(jì)的功能,所以有很多地方調(diào)用到了RateStatistics演顾。
RateStatistics 主要提供了四個(gè)公有函數(shù):
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函數(shù)就是各種參數(shù)重置了
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函數(shù)實(shí)際上在進(jìn)行添加的操作供搀。在添加之前先刪除舊的數(shù)據(jù),刪除舊的數(shù)據(jù)EraseOld钠至,實(shí)際上是按照一定的規(guī)則刪除的葛虐,如果沒(méi)有達(dá)到條件是不會(huì)刪除任何數(shù)據(jù)。
用當(dāng)前的值棕洋,減去最早的記錄值得到一個(gè)偏移量挡闰,偏移量加上最早的序號(hào),得到的值就是桶(buckets)的索引序號(hào)掰盘。oldest_time_ 和oldest_index_在這個(gè)函數(shù)中只是使用摄悯,這兩個(gè)值都是在刪除舊數(shù)據(jù)和重置的時(shí)候進(jìn)行修改(第一次插入數(shù)據(jù)除外)。
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);
}
這個(gè)函數(shù)就是獲取帶寬值了愧捕。這里有一個(gè)空值的返回奢驯,當(dāng)桶里面只有一個(gè)數(shù)據(jù)的時(shí)候,或者沒(méi)有達(dá)到最大的窗口大小直接返回一個(gè)空值次绘。其他情況才是對(duì)根據(jù)當(dāng)前的時(shí)間瘪阁,獲取一段時(shí)間內(nèi)(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;
}
刪除舊數(shù)據(jù)的函數(shù)邮偎。最早的數(shù)據(jù)oldest_time_小于 now_ms - current_window_size_ms_+1的時(shí)候才會(huì)觸發(fā)管跺,這時(shí)候一般情況下num_samples_會(huì)大于0。然后循環(huán)刪除最久的數(shù)據(jù)禾进。
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;
}
設(shè)置窗口大小的函數(shù)
bool RateStatistics::IsInitialized() const {
return oldest_time_ != -max_window_size_ms_;
}