Field trials for ProbeController when a network state estimate is known.
Ensure initial second probe can be disabled. Can configure separate probe duration if the network state estimate is known. Can probe immediately if network state estimate increase more than a factor Bug: webrtc:14392 Change-Id: Iefb980f0b10c7c51db62793c3bd3f187fc67593d Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/273349 Reviewed-by: Diep Bui <diepbp@webrtc.org> Commit-Queue: Per Kjellander <perkj@webrtc.org> Cr-Commit-Position: refs/heads/main@{#37966}
This commit is contained in:
committed by
WebRTC LUCI CQ
parent
d13686a26b
commit
43e11c881b
@ -24,7 +24,6 @@
|
||||
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
|
||||
#include "rtc_base/checks.h"
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
#include "system_wrappers/include/metrics.h"
|
||||
|
||||
namespace webrtc {
|
||||
@ -88,7 +87,12 @@ ProbeControllerConfig::ProbeControllerConfig(
|
||||
alr_probe_scale("alr_scale", 2),
|
||||
network_state_estimate_probing_interval("network_state_interval",
|
||||
TimeDelta::PlusInfinity()),
|
||||
network_state_estimate_fast_rampup_rate("network_state_fast_rampup_rate",
|
||||
0),
|
||||
network_state_probe_scale("network_state_scale", 1.0),
|
||||
network_state_probe_duration("network_state_probe_duration",
|
||||
TimeDelta::Millis(15)),
|
||||
|
||||
first_allocation_probe_scale("alloc_p1", 1),
|
||||
second_allocation_probe_scale("alloc_p2", 2),
|
||||
allocation_allow_further_probing("alloc_probe_further", false),
|
||||
@ -103,7 +107,8 @@ ProbeControllerConfig::ProbeControllerConfig(
|
||||
&alr_probing_interval, &alr_probe_scale, &first_allocation_probe_scale,
|
||||
&second_allocation_probe_scale, &allocation_allow_further_probing,
|
||||
&min_probe_duration, &network_state_estimate_probing_interval,
|
||||
&network_state_probe_scale, &probe_if_bwe_limited_due_to_loss},
|
||||
&network_state_estimate_fast_rampup_rate, &network_state_probe_scale,
|
||||
&network_state_probe_duration, &probe_if_bwe_limited_due_to_loss},
|
||||
key_value_config->Lookup("WebRTC-Bwe-ProbingConfiguration"));
|
||||
|
||||
// Specialized keys overriding subsets of WebRTC-Bwe-ProbingConfiguration
|
||||
@ -249,7 +254,8 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateExponentialProbing(
|
||||
// 1.2 Mbps to continue probing.
|
||||
std::vector<DataRate> probes = {config_.first_exponential_probe_scale *
|
||||
start_bitrate_};
|
||||
if (config_.second_exponential_probe_scale) {
|
||||
if (config_.second_exponential_probe_scale &&
|
||||
config_.second_exponential_probe_scale.GetOptional().value() > 0) {
|
||||
probes.push_back(config_.second_exponential_probe_scale.Value() *
|
||||
start_bitrate_);
|
||||
}
|
||||
@ -350,6 +356,14 @@ void ProbeController::SetMaxBitrate(DataRate max_bitrate) {
|
||||
|
||||
void ProbeController::SetNetworkStateEstimate(
|
||||
webrtc::NetworkStateEstimate estimate) {
|
||||
if (config_.network_state_estimate_fast_rampup_rate > 0 &&
|
||||
estimated_bitrate_ < estimate.link_capacity_upper &&
|
||||
(!network_estimate_ ||
|
||||
estimate.link_capacity_upper >=
|
||||
config_.network_state_estimate_fast_rampup_rate *
|
||||
network_estimate_->link_capacity_upper)) {
|
||||
send_probe_on_next_process_interval_ = true;
|
||||
}
|
||||
network_estimate_ = estimate;
|
||||
}
|
||||
|
||||
@ -370,6 +384,7 @@ void ProbeController::Reset(Timestamp at_time) {
|
||||
time_of_last_large_drop_ = now;
|
||||
bitrate_before_last_large_drop_ = DataRate::Zero();
|
||||
max_total_allocated_bitrate_ = DataRate::Zero();
|
||||
send_probe_on_next_process_interval_ = false;
|
||||
}
|
||||
|
||||
bool ProbeController::TimeForAlrProbe(Timestamp at_time) const {
|
||||
@ -407,7 +422,8 @@ std::vector<ProbeClusterConfig> ProbeController::Process(Timestamp at_time) {
|
||||
if (estimated_bitrate_.IsZero() || state_ != State::kProbingComplete) {
|
||||
return {};
|
||||
}
|
||||
if (TimeForAlrProbe(at_time) || TimeForNetworkStateProbe(at_time)) {
|
||||
if (send_probe_on_next_process_interval_ || TimeForAlrProbe(at_time) ||
|
||||
TimeForNetworkStateProbe(at_time)) {
|
||||
return InitiateProbing(
|
||||
at_time, {estimated_bitrate_ * config_.alr_probe_scale}, true);
|
||||
}
|
||||
@ -440,6 +456,7 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
|
||||
max_probe_bitrate =
|
||||
std::min(max_probe_bitrate, max_total_allocated_bitrate_ * 2);
|
||||
}
|
||||
send_probe_on_next_process_interval_ = false;
|
||||
|
||||
std::vector<ProbeClusterConfig> pending_probes;
|
||||
for (DataRate bitrate : bitrates_to_probe) {
|
||||
@ -453,7 +470,13 @@ std::vector<ProbeClusterConfig> ProbeController::InitiateProbing(
|
||||
ProbeClusterConfig config;
|
||||
config.at_time = now;
|
||||
config.target_data_rate = bitrate;
|
||||
config.target_duration = config_.min_probe_duration;
|
||||
if (network_estimate_ &&
|
||||
config_.network_state_estimate_probing_interval->IsFinite()) {
|
||||
config.target_duration = config_.network_state_probe_duration;
|
||||
} else {
|
||||
config.target_duration = config_.min_probe_duration;
|
||||
}
|
||||
|
||||
config.target_probe_count = config_.min_probe_packets_sent;
|
||||
config.id = next_probe_cluster_id_;
|
||||
next_probe_cluster_id_++;
|
||||
|
||||
@ -50,7 +50,13 @@ struct ProbeControllerConfig {
|
||||
|
||||
// Configures how often we send probes if NetworkStateEstimate is available.
|
||||
FieldTrialParameter<TimeDelta> network_state_estimate_probing_interval;
|
||||
// If the network state estimate increase more than this rate, a probe is sent
|
||||
// the next process interval.
|
||||
FieldTrialParameter<double> network_state_estimate_fast_rampup_rate;
|
||||
FieldTrialParameter<double> network_state_probe_scale;
|
||||
// Overrides min_probe_duration if network_state_estimate_probing_interval
|
||||
// is set and a network state estimate is known.
|
||||
FieldTrialParameter<TimeDelta> network_state_probe_duration;
|
||||
|
||||
// Configures the probes emitted by changed to the allocated bitrate.
|
||||
FieldTrialOptional<double> first_allocation_probe_scale;
|
||||
@ -142,6 +148,7 @@ class ProbeController {
|
||||
DataRate min_bitrate_to_probe_further_ = DataRate::PlusInfinity();
|
||||
Timestamp time_last_probing_initiated_ = Timestamp::MinusInfinity();
|
||||
DataRate estimated_bitrate_ = DataRate::Zero();
|
||||
bool send_probe_on_next_process_interval_;
|
||||
absl::optional<webrtc::NetworkStateEstimate> network_estimate_;
|
||||
DataRate start_bitrate_ = DataRate::Zero();
|
||||
DataRate max_bitrate_ = DataRate::PlusInfinity();
|
||||
|
||||
@ -108,6 +108,27 @@ TEST(ProbeControllerTest, ProbeOnlyWhenNetworkIsUp) {
|
||||
EXPECT_GE(probes.size(), 2u);
|
||||
}
|
||||
|
||||
TEST(ProbeControllerTest, CanConfigureInitialProbeRateFactor) {
|
||||
ProbeControllerFixture fixture("WebRTC-Bwe-ProbingConfiguration/p1:2,p2:3/");
|
||||
std::unique_ptr<ProbeController> probe_controller =
|
||||
fixture.CreateController();
|
||||
auto probes = probe_controller->SetBitrates(
|
||||
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
||||
EXPECT_EQ(probes.size(), 2u);
|
||||
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
|
||||
EXPECT_EQ(probes[1].target_data_rate, kStartBitrate * 3);
|
||||
}
|
||||
|
||||
TEST(ProbeControllerTest, DisableSecondInitialProbeIfRateFactorZero) {
|
||||
ProbeControllerFixture fixture("WebRTC-Bwe-ProbingConfiguration/p1:2,p2:0/");
|
||||
std::unique_ptr<ProbeController> probe_controller =
|
||||
fixture.CreateController();
|
||||
auto probes = probe_controller->SetBitrates(
|
||||
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
||||
EXPECT_EQ(probes.size(), 1u);
|
||||
EXPECT_EQ(probes[0].target_data_rate, kStartBitrate * 2);
|
||||
}
|
||||
|
||||
TEST(ProbeControllerTest, InitiatesProbingOnMaxBitrateIncrease) {
|
||||
ProbeControllerFixture fixture;
|
||||
std::unique_ptr<ProbeController> probe_controller =
|
||||
@ -632,5 +653,68 @@ TEST(ProbeControllerTest, AlrProbesLimitedByNetworkStateEstimate) {
|
||||
EXPECT_EQ(probes[0].target_data_rate, state_estimate.link_capacity_upper);
|
||||
}
|
||||
|
||||
TEST(ProbeControllerTest, CanSetLongerProbeDurationAfterNetworkStateEstimate) {
|
||||
ProbeControllerFixture fixture(
|
||||
"WebRTC-Bwe-ProbingConfiguration/"
|
||||
"network_state_interval:5s,network_state_probe_duration:100ms/");
|
||||
std::unique_ptr<ProbeController> probe_controller =
|
||||
fixture.CreateController();
|
||||
|
||||
auto probes = probe_controller->SetBitrates(
|
||||
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
||||
probes = probe_controller->SetEstimatedBitrate(
|
||||
DataRate::KilobitsPerSec(5), /*bwe_limited_due_to_packet_loss=*/false,
|
||||
fixture.CurrentTime());
|
||||
ASSERT_FALSE(probes.empty());
|
||||
EXPECT_LT(probes[0].target_duration, TimeDelta::Millis(100));
|
||||
|
||||
NetworkStateEstimate state_estimate;
|
||||
state_estimate.link_capacity_upper = DataRate::KilobitsPerSec(6);
|
||||
probe_controller->SetNetworkStateEstimate(state_estimate);
|
||||
fixture.AdvanceTime(TimeDelta::Seconds(5));
|
||||
probes = probe_controller->Process(fixture.CurrentTime());
|
||||
ASSERT_EQ(probes.size(), 1u);
|
||||
EXPECT_EQ(probes[0].target_duration, TimeDelta::Millis(100));
|
||||
}
|
||||
|
||||
TEST(ProbeControllerTest, ProbeAfterLargeNetworkStateChange) {
|
||||
ProbeControllerFixture fixture(
|
||||
"WebRTC-Bwe-ProbingConfiguration/"
|
||||
"network_state_interval:5s,network_state_fast_rampup_rate:2.0/");
|
||||
std::unique_ptr<ProbeController> probe_controller =
|
||||
fixture.CreateController();
|
||||
|
||||
auto probes = probe_controller->SetBitrates(
|
||||
kMinBitrate, kStartBitrate, kMaxBitrate, fixture.CurrentTime());
|
||||
probes = probe_controller->SetEstimatedBitrate(
|
||||
kStartBitrate, /*bwe_limited_due_to_packet_loss=*/false,
|
||||
fixture.CurrentTime());
|
||||
// Need to wait at least one second before process can trigger a new probe.
|
||||
fixture.AdvanceTime(TimeDelta::Millis(1100));
|
||||
probes = probe_controller->Process(fixture.CurrentTime());
|
||||
EXPECT_TRUE(probes.empty());
|
||||
|
||||
NetworkStateEstimate state_estimate;
|
||||
state_estimate.link_capacity_upper = kStartBitrate;
|
||||
probe_controller->SetNetworkStateEstimate(state_estimate);
|
||||
// No probe since NetworkStateEstimate is not higher than the set
|
||||
// estimated bitrate.
|
||||
probes = probe_controller->Process(fixture.CurrentTime());
|
||||
EXPECT_TRUE(probes.empty());
|
||||
|
||||
// If NetworkState increase just a bit, dont expect the probe to be sent
|
||||
// immediately.
|
||||
state_estimate.link_capacity_upper = kStartBitrate * 1.4;
|
||||
probe_controller->SetNetworkStateEstimate(state_estimate);
|
||||
probes = probe_controller->Process(fixture.CurrentTime());
|
||||
EXPECT_TRUE(probes.empty());
|
||||
|
||||
// If NetworkState increase dramatically, expect a probe to be sent.
|
||||
state_estimate.link_capacity_upper = kStartBitrate * 1.4 * 2;
|
||||
probe_controller->SetNetworkStateEstimate(state_estimate);
|
||||
probes = probe_controller->Process(fixture.CurrentTime());
|
||||
EXPECT_EQ(probes.size(), 1u);
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace webrtc
|
||||
|
||||
Reference in New Issue
Block a user