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:
Per Kjellander
2022-08-30 20:43:51 +02:00
committed by WebRTC LUCI CQ
parent d13686a26b
commit 43e11c881b
3 changed files with 119 additions and 5 deletions

View File

@ -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_++;

View File

@ -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();

View File

@ -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