mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-20 09:07:52 +01:00
Adds utility function for PCC.
Bug: webrtc:9434 Change-Id: I840f39afdff1851d939005f82e64b23927bf455e Reviewed-on: https://webrtc-review.googlesource.com/87146 Commit-Queue: Anastasia Koloskova <koloskova@webrtc.org> Reviewed-by: Björn Terelius <terelius@webrtc.org> Reviewed-by: Sebastian Jansson <srte@webrtc.org> Cr-Commit-Position: refs/heads/master@{#24369}
This commit is contained in:
parent
9171e78ccd
commit
ddbbf4601b
4 changed files with 279 additions and 0 deletions
|
@ -30,16 +30,30 @@ rtc_static_library("rtt_tracker") {
|
|||
]
|
||||
}
|
||||
|
||||
rtc_static_library("utility_function") {
|
||||
sources = [
|
||||
"utility_function.cc",
|
||||
"utility_function.h",
|
||||
]
|
||||
deps = [
|
||||
":monitor_interval",
|
||||
"../../../api/transport:network_control",
|
||||
"../../../rtc_base:rtc_base_approved",
|
||||
]
|
||||
}
|
||||
|
||||
if (rtc_include_tests) {
|
||||
rtc_source_set("pcc_unittests") {
|
||||
testonly = true
|
||||
sources = [
|
||||
"monitor_interval_unittest.cc",
|
||||
"rtt_tracker_unittest.cc",
|
||||
"utility_function_unittest.cc",
|
||||
]
|
||||
deps = [
|
||||
":monitor_interval",
|
||||
":rtt_tracker",
|
||||
":utility_function",
|
||||
"../../../api/transport:network_control_test",
|
||||
"../../../api/units:data_rate",
|
||||
"../../../api/units:time_delta",
|
||||
|
|
84
modules/congestion_controller/pcc/utility_function.cc
Normal file
84
modules/congestion_controller/pcc/utility_function.cc
Normal file
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include "modules/congestion_controller/pcc/utility_function.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
|
||||
namespace webrtc {
|
||||
namespace pcc {
|
||||
|
||||
VivaceUtilityFunction::VivaceUtilityFunction(
|
||||
double delay_gradient_coefficient,
|
||||
double loss_coefficient,
|
||||
double throughput_coefficient,
|
||||
double throughput_power,
|
||||
double delay_gradient_threshold,
|
||||
double delay_gradient_negative_bound)
|
||||
: delay_gradient_coefficient_(delay_gradient_coefficient),
|
||||
loss_coefficient_(loss_coefficient),
|
||||
throughput_power_(throughput_power),
|
||||
throughput_coefficient_(throughput_coefficient),
|
||||
delay_gradient_threshold_(delay_gradient_threshold),
|
||||
delay_gradient_negative_bound_(delay_gradient_negative_bound) {
|
||||
RTC_DCHECK_GE(delay_gradient_negative_bound_, 0);
|
||||
}
|
||||
|
||||
double VivaceUtilityFunction::Compute(
|
||||
const PccMonitorInterval& monitor_interval) const {
|
||||
RTC_DCHECK(monitor_interval.IsFeedbackCollectionDone());
|
||||
double bitrate = monitor_interval.GetTargetSendingRate().bps();
|
||||
double loss_rate = monitor_interval.GetLossRate();
|
||||
double rtt_gradient =
|
||||
monitor_interval.ComputeDelayGradient(delay_gradient_threshold_);
|
||||
rtt_gradient = std::max(rtt_gradient, -delay_gradient_negative_bound_);
|
||||
return (throughput_coefficient_ * std::pow(bitrate, throughput_power_)) -
|
||||
(delay_gradient_coefficient_ * bitrate * rtt_gradient) -
|
||||
(loss_coefficient_ * bitrate * loss_rate);
|
||||
}
|
||||
|
||||
VivaceUtilityFunction::~VivaceUtilityFunction() = default;
|
||||
|
||||
ModifiedVivaceUtilityFunction::ModifiedVivaceUtilityFunction(
|
||||
double delay_gradient_coefficient,
|
||||
double loss_coefficient,
|
||||
double throughput_coefficient,
|
||||
double throughput_power,
|
||||
double delay_gradient_threshold,
|
||||
double delay_gradient_negative_bound)
|
||||
: delay_gradient_coefficient_(delay_gradient_coefficient),
|
||||
loss_coefficient_(loss_coefficient),
|
||||
throughput_power_(throughput_power),
|
||||
throughput_coefficient_(throughput_coefficient),
|
||||
delay_gradient_threshold_(delay_gradient_threshold),
|
||||
delay_gradient_negative_bound_(delay_gradient_negative_bound) {
|
||||
RTC_DCHECK_GE(delay_gradient_negative_bound_, 0);
|
||||
}
|
||||
|
||||
double ModifiedVivaceUtilityFunction::Compute(
|
||||
const PccMonitorInterval& monitor_interval) const {
|
||||
RTC_DCHECK(monitor_interval.IsFeedbackCollectionDone());
|
||||
double bitrate = monitor_interval.GetTargetSendingRate().bps();
|
||||
double loss_rate = monitor_interval.GetLossRate();
|
||||
double rtt_gradient =
|
||||
monitor_interval.ComputeDelayGradient(delay_gradient_threshold_);
|
||||
rtt_gradient = std::max(rtt_gradient, -delay_gradient_negative_bound_);
|
||||
return (throughput_coefficient_ * std::pow(bitrate, throughput_power_) *
|
||||
bitrate) -
|
||||
(delay_gradient_coefficient_ * bitrate * bitrate * rtt_gradient) -
|
||||
(loss_coefficient_ * bitrate * bitrate * loss_rate);
|
||||
}
|
||||
|
||||
ModifiedVivaceUtilityFunction::~ModifiedVivaceUtilityFunction() = default;
|
||||
|
||||
} // namespace pcc
|
||||
} // namespace webrtc
|
79
modules/congestion_controller/pcc/utility_function.h
Normal file
79
modules/congestion_controller/pcc/utility_function.h
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#ifndef MODULES_CONGESTION_CONTROLLER_PCC_UTILITY_FUNCTION_H_
|
||||
#define MODULES_CONGESTION_CONTROLLER_PCC_UTILITY_FUNCTION_H_
|
||||
|
||||
#include "api/transport/network_control.h"
|
||||
#include "modules/congestion_controller/pcc/monitor_interval.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace pcc {
|
||||
|
||||
// Utility function is used by PCC to transform the performance statistics
|
||||
// (sending rate, loss rate, packets latency) gathered at one monitor interval
|
||||
// into a numerical value.
|
||||
// https://www.usenix.org/conference/nsdi18/presentation/dong
|
||||
class PccUtilityFunctionInterface {
|
||||
public:
|
||||
virtual double Compute(const PccMonitorInterval& monitor_interval) const = 0;
|
||||
virtual ~PccUtilityFunctionInterface() = default;
|
||||
};
|
||||
|
||||
// Vivace utility function were suggested in the paper "PCC Vivace:
|
||||
// Online-Learning Congestion Control", Mo Dong et all.
|
||||
class VivaceUtilityFunction : public PccUtilityFunctionInterface {
|
||||
public:
|
||||
VivaceUtilityFunction(double delay_gradient_coefficient,
|
||||
double loss_coefficient,
|
||||
double throughput_coefficient,
|
||||
double throughput_power,
|
||||
double delay_gradient_threshold,
|
||||
double delay_gradient_negative_bound);
|
||||
double Compute(const PccMonitorInterval& monitor_interval) const override;
|
||||
~VivaceUtilityFunction() override;
|
||||
|
||||
private:
|
||||
const double delay_gradient_coefficient_;
|
||||
const double loss_coefficient_;
|
||||
const double throughput_power_;
|
||||
const double throughput_coefficient_;
|
||||
const double delay_gradient_threshold_;
|
||||
const double delay_gradient_negative_bound_;
|
||||
};
|
||||
|
||||
// This utility function were obtained by tuning Vivace utility function.
|
||||
// The main difference is that gradient of modified utilify funtion (as well as
|
||||
// rate updates) scales proportionally to the sending rate which leads to
|
||||
// better performance in case of single sender.
|
||||
class ModifiedVivaceUtilityFunction : public PccUtilityFunctionInterface {
|
||||
public:
|
||||
ModifiedVivaceUtilityFunction(double delay_gradient_coefficient,
|
||||
double loss_coefficient,
|
||||
double throughput_coefficient,
|
||||
double throughput_power,
|
||||
double delay_gradient_threshold,
|
||||
double delay_gradient_negative_bound);
|
||||
double Compute(const PccMonitorInterval& monitor_interval) const override;
|
||||
~ModifiedVivaceUtilityFunction() override;
|
||||
|
||||
private:
|
||||
const double delay_gradient_coefficient_;
|
||||
const double loss_coefficient_;
|
||||
const double throughput_power_;
|
||||
const double throughput_coefficient_;
|
||||
const double delay_gradient_threshold_;
|
||||
const double delay_gradient_negative_bound_;
|
||||
};
|
||||
|
||||
} // namespace pcc
|
||||
} // namespace webrtc
|
||||
|
||||
#endif // MODULES_CONGESTION_CONTROLLER_PCC_UTILITY_FUNCTION_H_
|
102
modules/congestion_controller/pcc/utility_function_unittest.cc
Normal file
102
modules/congestion_controller/pcc/utility_function_unittest.cc
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (c) 2018 The WebRTC project authors. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license
|
||||
* that can be found in the LICENSE file in the root of the source
|
||||
* tree. An additional intellectual property rights grant can be found
|
||||
* in the file PATENTS. All contributing project authors may
|
||||
* be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "modules/congestion_controller/pcc/utility_function.h"
|
||||
#include "test/gtest.h"
|
||||
|
||||
namespace webrtc {
|
||||
namespace pcc {
|
||||
namespace test {
|
||||
namespace {
|
||||
constexpr double kLossCoefficient = 11.35;
|
||||
constexpr double kThroughputPower = 0.9;
|
||||
constexpr double kThroughputCoefficient = 1;
|
||||
constexpr double kDelayGradientNegativeBound = 10;
|
||||
|
||||
const Timestamp kStartTime = Timestamp::us(0);
|
||||
const TimeDelta kPacketsDelta = TimeDelta::ms(1);
|
||||
const TimeDelta kIntervalDuration = TimeDelta::ms(100);
|
||||
const DataRate kSendingBitrate = DataRate::bps(1000);
|
||||
|
||||
const DataSize kDefaultDataSize = DataSize::bytes(100);
|
||||
const TimeDelta kDefaultDelay = TimeDelta::ms(100);
|
||||
|
||||
std::vector<PacketResult> CreatePacketResults(
|
||||
const std::vector<Timestamp>& packets_send_times,
|
||||
const std::vector<Timestamp>& packets_received_times = {},
|
||||
const std::vector<DataSize>& packets_sizes = {}) {
|
||||
std::vector<PacketResult> packet_results;
|
||||
PacketResult packet_result;
|
||||
SentPacket sent_packet;
|
||||
for (size_t i = 0; i < packets_send_times.size(); ++i) {
|
||||
sent_packet.send_time = packets_send_times[i];
|
||||
if (packets_sizes.empty()) {
|
||||
sent_packet.size = kDefaultDataSize;
|
||||
} else {
|
||||
sent_packet.size = packets_sizes[i];
|
||||
}
|
||||
packet_result.sent_packet = sent_packet;
|
||||
if (packets_received_times.empty()) {
|
||||
packet_result.receive_time = packets_send_times[i] + kDefaultDelay;
|
||||
} else {
|
||||
packet_result.receive_time = packets_received_times[i];
|
||||
}
|
||||
packet_results.push_back(packet_result);
|
||||
}
|
||||
return packet_results;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TEST(PccVivaceUtilityFunctionTest,
|
||||
UtilityIsThroughputTermIfAllRestCoefficientsAreZero) {
|
||||
VivaceUtilityFunction utility_function(0, 0, kThroughputCoefficient,
|
||||
kThroughputPower, 0,
|
||||
kDelayGradientNegativeBound);
|
||||
PccMonitorInterval monitor_interval(kSendingBitrate, kStartTime,
|
||||
kIntervalDuration);
|
||||
monitor_interval.OnPacketsFeedback(CreatePacketResults(
|
||||
{kStartTime + kPacketsDelta, kStartTime + 2 * kPacketsDelta,
|
||||
kStartTime + 3 * kPacketsDelta, kStartTime + 2 * kIntervalDuration},
|
||||
{kStartTime + kPacketsDelta + kDefaultDelay, Timestamp::Infinity(),
|
||||
kStartTime + kDefaultDelay + 3 * kPacketsDelta, Timestamp::Infinity()},
|
||||
{kDefaultDataSize, kDefaultDataSize, kDefaultDataSize,
|
||||
kDefaultDataSize}));
|
||||
EXPECT_DOUBLE_EQ(utility_function.Compute(monitor_interval),
|
||||
kThroughputCoefficient *
|
||||
std::pow(kSendingBitrate.bps(), kThroughputPower));
|
||||
}
|
||||
|
||||
TEST(PccVivaceUtilityFunctionTest,
|
||||
LossTermIsNonZeroIfLossCoefficientIsNonZero) {
|
||||
VivaceUtilityFunction utility_function(
|
||||
0, kLossCoefficient, kThroughputCoefficient, kThroughputPower, 0,
|
||||
kDelayGradientNegativeBound);
|
||||
PccMonitorInterval monitor_interval(kSendingBitrate, kStartTime,
|
||||
kIntervalDuration);
|
||||
monitor_interval.OnPacketsFeedback(CreatePacketResults(
|
||||
{kStartTime + kPacketsDelta, kStartTime + 2 * kPacketsDelta,
|
||||
kStartTime + 5 * kPacketsDelta, kStartTime + 2 * kIntervalDuration},
|
||||
{kStartTime + kDefaultDelay, Timestamp::Infinity(),
|
||||
kStartTime + kDefaultDelay, kStartTime + 3 * kIntervalDuration},
|
||||
{}));
|
||||
// The second packet was lost.
|
||||
EXPECT_DOUBLE_EQ(utility_function.Compute(monitor_interval),
|
||||
kThroughputCoefficient *
|
||||
std::pow(kSendingBitrate.bps(), kThroughputPower) -
|
||||
kLossCoefficient * kSendingBitrate.bps() *
|
||||
monitor_interval.GetLossRate());
|
||||
}
|
||||
|
||||
} // namespace test
|
||||
} // namespace pcc
|
||||
} // namespace webrtc
|
Loading…
Reference in a new issue