WebRTC 源码阅读笔记之 AlrDetector
Table of Contents
Overview
ALR(Application limited region detector)的基本原理就是
SentBitRate/EstimatedBitRate 的百分比与 kAlrStartUsagePercent(50)做比较,当小于该值认为网络受限,需要启动 probe 重新探测带宽,当大于 kAlrEndUsagePercent(80),认为网络恢复, 停止进行启动下次 probe 探测
AlrDetectorConfig
发送流量比率(sent_bitrate/estimated_bitrate) 作为网络容量的函数,用于确定应用程序受限区域 ALR(Application-Limited Region)。
ALR 区域在带宽剩余率大于 kAlrStartUsageRatio (默认为0.8) 时开始,在带宽剩余率大于 kAlrEndUsageRatio (默认为 0.5) 时结束。
注意:
- 带宽剩余率 = 1 - send_bitrate/estimated_bitrate
- 在对应用有限区域的 BW 调整进行有效微调之前,这是有意做了一些保守的。
struct AlrDetectorConfig {
// Sent traffic ratio as a function of network capacity used to determine
// application-limited region. ALR region start when bandwidth usage drops
// below kAlrStartUsageRatio and ends when it raises above
// kAlrEndUsageRatio. NOTE: This is intentionally conservative at the moment
// until BW adjustments of application limited region is fine tuned.
double bandwidth_usage_ratio = 0.65;
double start_budget_level_ratio = 0.80;
double stop_budget_level_ratio = 0.50;
std::unique_ptr<StructParametersParser> Parser();
};
IntervalBudget
在一定时间间隔内的预算(可使用字节数)
class IntervalBudget {
public:
explicit IntervalBudget(int initial_target_rate_kbps);
IntervalBudget(int initial_target_rate_kbps, bool can_build_up_underuse);
void set_target_rate_kbps(int target_rate_kbps);
// TODO(tschumim): Unify IncreaseBudget and UseBudget to one function.
void IncreaseBudget(int64_t delta_time_ms);
void UseBudget(size_t bytes);
size_t bytes_remaining() const;
double budget_ratio() const;
int target_rate_kbps() const;
private:
//目标码率
int target_rate_kbps_;
//最大预算字节数
int64_t max_bytes_in_budget_;
//剩余字节数
int64_t bytes_remaining_;
//是否构建使用不足?
bool can_build_up_underuse_;
};
IntervalBudget::IntervalBudget(int initial_target_rate_kbps)
: IntervalBudget(initial_target_rate_kbps, false) {}
IntervalBudget::IntervalBudget(int initial_target_rate_kbps,
bool can_build_up_underuse)
: bytes_remaining_(0), can_build_up_underuse_(can_build_up_underuse) {
set_target_rate_kbps(initial_target_rate_kbps);
}
void IntervalBudget::set_target_rate_kbps(int target_rate_kbps) {
target_rate_kbps_ = target_rate_kbps;
max_bytes_in_budget_ = (kWindowMs * target_rate_kbps_) / 8;
bytes_remaining_ = std::min(std::max(-max_bytes_in_budget_, bytes_remaining_),
max_bytes_in_budget_);
}
//增大预算
void IntervalBudget::IncreaseBudget(int64_t delta_time_ms) {
int64_t bytes = target_rate_kbps_ * delta_time_ms / 8;
if (bytes_remaining_ < 0 || can_build_up_underuse_) {
// We overused last interval, compensate this interval.
bytes_remaining_ = std::min(bytes_remaining_ + bytes, max_bytes_in_budget_);
} else {
// If we underused last interval we can't use it this interval.
bytes_remaining_ = std::min(bytes, max_bytes_in_budget_);
}
}
//使用预算: 剩余的字节数再减法传入的字节数
void IntervalBudget::UseBudget(size_t bytes) {
bytes_remaining_ = std::max(bytes_remaining_ - static_cast<int>(bytes),
-max_bytes_in_budget_);
}
size_t IntervalBudget::bytes_remaining() const {
return rtc::saturated_cast<size_t>(std::max<int64_t>(0, bytes_remaining_));
}
//预算剩余率: 剩余的字节/最大预算字节数
double IntervalBudget::budget_ratio() const {
if (max_bytes_in_budget_ == 0)
return 0.0;
return static_cast<double>(bytes_remaining_) / max_bytes_in_budget_;
}
AlrDetector
应用程序受限区域检测器 AlrDetector 是一个类,它利用经过的时间和发送的字节的信号来估计当前网络流量是否受到应用程序生成流量的能力的限制。
AlrDetector提供了一个信号,可用于调整估计带宽。
注意:这个类不是线程安全的。
// Application limited region detector is a class that utilizes signals of
// elapsed time and bytes sent to estimate whether network traffic is
// currently limited by the application's ability to generate traffic.
//
// AlrDetector provides a signal that can be utilized to adjust
// estimate bandwidth.
// Note: This class is not thread-safe.
class AlrDetector {
public:
AlrDetector(AlrDetectorConfig config, RtcEventLog* event_log);
explicit AlrDetector(const WebRtcKeyValueConfig* key_value_config);
AlrDetector(const WebRtcKeyValueConfig* key_value_config,
RtcEventLog* event_log);
~AlrDetector();
void OnBytesSent(size_t bytes_sent, int64_t send_time_ms);
// Set current estimated bandwidth.
void SetEstimatedBitrate(int bitrate_bps);
// Returns time in milliseconds when the current application-limited region
// started or empty result if the sender is currently not application-limited.
absl::optional<int64_t> GetApplicationLimitedRegionStartTime() const;
private:
friend class GoogCcStatePrinter;
const AlrDetectorConfig conf_;
absl::optional<int64_t> last_send_time_ms_;
IntervalBudget alr_budget_;
absl::optional<int64_t> alr_started_time_ms_;
RtcEventLog* event_log_;
};
AlrDetector::OnBytesSent
void AlrDetector::OnBytesSent(size_t bytes_sent, int64_t send_time_ms) {
if (!last_send_time_ms_.has_value()) {
last_send_time_ms_ = send_time_ms;
// Since the duration for sending the bytes is unknwon, return without
// updating alr state.
return;
}
int64_t delta_time_ms = send_time_ms - *last_send_time_ms_;
last_send_time_ms_ = send_time_ms;
alr_budget_.UseBudget(bytes_sent);
alr_budget_.IncreaseBudget(delta_time_ms);
bool state_changed = false;
//如果剩余字节比率 大于 start_budget_level_ratio, 应用程序受限,没有充分利用带宽, 应该启动探测,设置 alr_started_time_ms_= 当前时间
if (alr_budget_.budget_ratio() > conf_.start_budget_level_ratio &&
!alr_started_time_ms_) {
alr_started_time_ms_.emplace(rtc::TimeMillis());
state_changed = true;
} //如果剩余字节比率 小于 stop_budget_level_ratio, 带宽利用的还可以, 应该停止探测 alr_started_time_ms_= 0
else if (alr_budget_.budget_ratio() < conf_.stop_budget_level_ratio &&
alr_started_time_ms_) {
state_changed = true;
alr_started_time_ms_.reset();
}
if (event_log_ && state_changed) {
event_log_->Log(
std::make_unique<RtcEventAlrState>(alr_started_time_ms_.has_value()));
}
}
Comments |0|
Category: WebRTC