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:

committed by
Commit Bot

parent
9171e78ccd
commit
ddbbf4601b
@ -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) {
|
if (rtc_include_tests) {
|
||||||
rtc_source_set("pcc_unittests") {
|
rtc_source_set("pcc_unittests") {
|
||||||
testonly = true
|
testonly = true
|
||||||
sources = [
|
sources = [
|
||||||
"monitor_interval_unittest.cc",
|
"monitor_interval_unittest.cc",
|
||||||
"rtt_tracker_unittest.cc",
|
"rtt_tracker_unittest.cc",
|
||||||
|
"utility_function_unittest.cc",
|
||||||
]
|
]
|
||||||
deps = [
|
deps = [
|
||||||
":monitor_interval",
|
":monitor_interval",
|
||||||
":rtt_tracker",
|
":rtt_tracker",
|
||||||
|
":utility_function",
|
||||||
"../../../api/transport:network_control_test",
|
"../../../api/transport:network_control_test",
|
||||||
"../../../api/units:data_rate",
|
"../../../api/units:data_rate",
|
||||||
"../../../api/units:time_delta",
|
"../../../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
|
Reference in New Issue
Block a user