Merge pull request #7532 from Atlante45/feat/delayed-decrease

Delay congestion epochs first decrease
This commit is contained in:
Seth Alves 2016-04-01 18:07:43 -07:00
commit 6025a66fa1
5 changed files with 34 additions and 24 deletions

View file

@ -82,11 +82,11 @@ void AssetServer::completeSetup() {
auto maxBandwidthFloat = maxBandwidthValue.toDouble(-1); auto maxBandwidthFloat = maxBandwidthValue.toDouble(-1);
if (maxBandwidthFloat > 0.0) { if (maxBandwidthFloat > 0.0) {
const int BYTES_PER_MEGABITS = (1024 * 1024) / 8; const int BITS_PER_MEGABITS = 1000 * 1000;
int maxBandwidth = maxBandwidthFloat * BYTES_PER_MEGABITS; int maxBandwidth = maxBandwidthFloat * BITS_PER_MEGABITS;
nodeList->setConnectionMaxBandwidth(maxBandwidth); nodeList->setConnectionMaxBandwidth(maxBandwidth);
qInfo() << "Set maximum bandwith per connection to" << maxBandwidthFloat << "Mb/s." qInfo() << "Set maximum bandwith per connection to" << maxBandwidthFloat << "Mb/s."
" (" << maxBandwidth << "bytes/sec)"; " (" << maxBandwidth << "bits/s)";
} }
// get the path to the asset folder from the domain server settings // get the path to the asset folder from the domain server settings

View file

@ -19,6 +19,7 @@ using namespace udt;
using namespace std::chrono; using namespace std::chrono;
static const double USECS_PER_SECOND = 1000000.0; static const double USECS_PER_SECOND = 1000000.0;
static const int BITS_PER_BYTE = 8;
void CongestionControl::setMaxBandwidth(int maxBandwidth) { void CongestionControl::setMaxBandwidth(int maxBandwidth) {
_maxBandwidth = maxBandwidth; _maxBandwidth = maxBandwidth;
@ -28,11 +29,11 @@ void CongestionControl::setMaxBandwidth(int maxBandwidth) {
void CongestionControl::setPacketSendPeriod(double newSendPeriod) { void CongestionControl::setPacketSendPeriod(double newSendPeriod) {
Q_ASSERT_X(newSendPeriod >= 0, "CongestionControl::setPacketPeriod", "Can not set a negative packet send period"); Q_ASSERT_X(newSendPeriod >= 0, "CongestionControl::setPacketPeriod", "Can not set a negative packet send period");
auto maxBandwidth = _maxBandwidth.load(); auto packetsPerSecond = (double)_maxBandwidth / (BITS_PER_BYTE * _mss);
if (maxBandwidth > 0) { if (packetsPerSecond > 0.0) {
// anytime the packet send period is about to be increased, make sure it stays below the minimum period, // anytime the packet send period is about to be increased, make sure it stays below the minimum period,
// calculated based on the maximum desired bandwidth // calculated based on the maximum desired bandwidth
double minPacketSendPeriod = USECS_PER_SECOND / (((double) maxBandwidth) / _mss); double minPacketSendPeriod = USECS_PER_SECOND / packetsPerSecond;
_packetSendPeriod = std::max(newSendPeriod, minPacketSendPeriod); _packetSendPeriod = std::max(newSendPeriod, minPacketSendPeriod);
} else { } else {
_packetSendPeriod = newSendPeriod; _packetSendPeriod = newSendPeriod;
@ -145,17 +146,23 @@ void DefaultCC::onLoss(SequenceNumber rangeStart, SequenceNumber rangeEnd) {
} }
_loss = true; _loss = true;
++_nakCount;
static const double INTER_PACKET_ARRIVAL_INCREASE = 1.125; static const double INTER_PACKET_ARRIVAL_INCREASE = 1.125;
static const int MAX_DECREASES_PER_CONGESTION_EPOCH = 5; static const int MAX_DECREASES_PER_CONGESTION_EPOCH = 5;
// check if this NAK starts a new congestion period - this will be the case if the // check if this NAK starts a new congestion period - this will be the case if the
// NAK received occured for a packet sent after the last decrease // NAK received occured for a packet sent after the last decrease
if (rangeStart > _lastDecreaseMaxSeq) { if (rangeStart > _lastDecreaseMaxSeq) {
_delayedDecrease = (rangeStart == rangeEnd);
_lastDecreasePeriod = _packetSendPeriod; _lastDecreasePeriod = _packetSendPeriod;
setPacketSendPeriod(ceil(_packetSendPeriod * INTER_PACKET_ARRIVAL_INCREASE)); if (!_delayedDecrease) {
setPacketSendPeriod(ceil(_packetSendPeriod * INTER_PACKET_ARRIVAL_INCREASE));
} else {
_loss = false;
}
// use EWMA to update the average number of NAKs per congestion // use EWMA to update the average number of NAKs per congestion
static const double NAK_EWMA_ALPHA = 0.125; static const double NAK_EWMA_ALPHA = 0.125;
@ -177,10 +184,12 @@ void DefaultCC::onLoss(SequenceNumber rangeStart, SequenceNumber rangeEnd) {
_randomDecreaseThreshold = distribution(generator); _randomDecreaseThreshold = distribution(generator);
} }
} else if ((_decreaseCount++ < MAX_DECREASES_PER_CONGESTION_EPOCH) && ((++_nakCount % _randomDecreaseThreshold) == 0)) { } else if (_delayedDecrease && _nakCount == 2) {
setPacketSendPeriod(ceil(_packetSendPeriod * INTER_PACKET_ARRIVAL_INCREASE));
} else if ((_decreaseCount++ < MAX_DECREASES_PER_CONGESTION_EPOCH) && ((_nakCount % _randomDecreaseThreshold) == 0)) {
// there have been fewer than MAX_DECREASES_PER_CONGESTION_EPOCH AND this NAK matches the random count at which we // there have been fewer than MAX_DECREASES_PER_CONGESTION_EPOCH AND this NAK matches the random count at which we
// decided we would decrease the packet send period // decided we would decrease the packet send period
setPacketSendPeriod(ceil(_packetSendPeriod * INTER_PACKET_ARRIVAL_INCREASE)); setPacketSendPeriod(ceil(_packetSendPeriod * INTER_PACKET_ARRIVAL_INCREASE));
_lastDecreaseMaxSeq = _sendCurrSeqNum; _lastDecreaseMaxSeq = _sendCurrSeqNum;
} }

View file

@ -15,7 +15,6 @@
#include <atomic> #include <atomic>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <memory>
#include <PortableHighResolutionClock.h> #include <PortableHighResolutionClock.h>
@ -61,7 +60,7 @@ protected:
double _congestionWindowSize { 16.0 }; // Congestion window size, in packets double _congestionWindowSize { 16.0 }; // Congestion window size, in packets
int _bandwidth { 0 }; // estimated bandwidth, packets per second int _bandwidth { 0 }; // estimated bandwidth, packets per second
std::atomic<int> _maxBandwidth { -1 }; // Maximum desired bandwidth, bytes per second std::atomic<int> _maxBandwidth { -1 }; // Maximum desired bandwidth, bits per second
double _maxCongestionWindowSize { 0.0 }; // maximum cwnd size, in packets double _maxCongestionWindowSize { 0.0 }; // maximum cwnd size, in packets
int _mss { 0 }; // Maximum Packet Size, including all packet headers int _mss { 0 }; // Maximum Packet Size, including all packet headers
@ -124,6 +123,7 @@ private:
int _randomDecreaseThreshold { 1 }; // random threshold on decrease by number of loss events int _randomDecreaseThreshold { 1 }; // random threshold on decrease by number of loss events
int _avgNAKNum { 0 }; // average number of NAKs per congestion int _avgNAKNum { 0 }; // average number of NAKs per congestion
int _decreaseCount { 0 }; // number of decreases in a congestion epoch int _decreaseCount { 0 }; // number of decreases in a congestion epoch
bool _delayedDecrease { false };
}; };
} }

View file

@ -354,7 +354,7 @@ void Socket::setCongestionControlFactory(std::unique_ptr<CongestionControlVirtua
void Socket::setConnectionMaxBandwidth(int maxBandwidth) { void Socket::setConnectionMaxBandwidth(int maxBandwidth) {
qInfo() << "Setting socket's maximum bandwith to" << maxBandwidth << ". (" qInfo() << "Setting socket's maximum bandwith to" << maxBandwidth << "bps. ("
<< _connectionsHash.size() << "live connections)"; << _connectionsHash.size() << "live connections)";
_maxBandwidth = maxBandwidth; _maxBandwidth = maxBandwidth;
for (auto& pair : _connectionsHash) { for (auto& pair : _connectionsHash) {

View file

@ -57,13 +57,13 @@ const QCommandLineOption STATS_INTERVAL {
}; };
const QStringList CLIENT_STATS_TABLE_HEADERS { const QStringList CLIENT_STATS_TABLE_HEADERS {
"Send (P/s)", "Est. Max (P/s)", "RTT (ms)", "CW (P)", "Period (us)", "Send (Mb/s)", "Est. Max (Mb/s)", "RTT (ms)", "CW (P)", "Period (us)",
"Recv ACK", "Procd ACK", "Recv LACK", "Recv NAK", "Recv TNAK", "Recv ACK", "Procd ACK", "Recv LACK", "Recv NAK", "Recv TNAK",
"Sent ACK2", "Sent Packets", "Re-sent Packets" "Sent ACK2", "Sent Packets", "Re-sent Packets"
}; };
const QStringList SERVER_STATS_TABLE_HEADERS { const QStringList SERVER_STATS_TABLE_HEADERS {
" Mb/s ", "Recv P/s", "Est. Max (P/s)", "RTT (ms)", "CW (P)", " Mb/s ", "Recv Mb/s", "Est. Max (Mb/s)", "RTT (ms)", "CW (P)",
"Sent ACK", "Sent LACK", "Sent NAK", "Sent TNAK", "Sent ACK", "Sent LACK", "Sent NAK", "Sent TNAK",
"Recv ACK2", "Duplicates (P)" "Recv ACK2", "Duplicates (P)"
}; };
@ -364,7 +364,11 @@ void UDTTest::handleMessage(std::unique_ptr<Message> message) {
void UDTTest::sampleStats() { void UDTTest::sampleStats() {
static bool first = true; static bool first = true;
static const double USECS_PER_MSEC = 1000.0; static const double USECS_PER_MSEC = 1000.0;
static const double MEGABITS_PER_BYTE = 8.0 / 1000000.0;
static const double MS_PER_SECOND = 1000.0;
static const double PPS_TO_MBPS = 1500.0 * MEGABITS_PER_BYTE;
if (!_target.isNull()) { if (!_target.isNull()) {
if (first) { if (first) {
// output the headers for stats for our table // output the headers for stats for our table
@ -378,8 +382,8 @@ void UDTTest::sampleStats() {
// setup a list of left justified values // setup a list of left justified values
QStringList values { QStringList values {
QString::number(stats.sendRate).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.sendRate * PPS_TO_MBPS).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.estimatedBandwith).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.estimatedBandwith * PPS_TO_MBPS).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.rtt / USECS_PER_MSEC, 'f', 2).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.rtt / USECS_PER_MSEC, 'f', 2).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.congestionWindowSize).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.congestionWindowSize).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.packetSendPeriod).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.packetSendPeriod).rightJustified(CLIENT_STATS_TABLE_HEADERS[++headerIndex].size()),
@ -408,16 +412,13 @@ void UDTTest::sampleStats() {
int headerIndex = -1; int headerIndex = -1;
static const double MEGABITS_PER_BYTE = 8.0 / 1000000.0;
static const double MS_PER_SECOND = 1000.0;
double megabitsPerSecond = (stats.receivedBytes * MEGABITS_PER_BYTE * MS_PER_SECOND) / _statsInterval; double megabitsPerSecond = (stats.receivedBytes * MEGABITS_PER_BYTE * MS_PER_SECOND) / _statsInterval;
// setup a list of left justified values // setup a list of left justified values
QStringList values { QStringList values {
QString::number(megabitsPerSecond, 'f', 2).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(megabitsPerSecond, 'f', 2).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.receiveRate).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.receiveRate * PPS_TO_MBPS).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.estimatedBandwith).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.estimatedBandwith * PPS_TO_MBPS).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.rtt / USECS_PER_MSEC, 'f', 2).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.rtt / USECS_PER_MSEC, 'f', 2).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.congestionWindowSize).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.congestionWindowSize).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()),
QString::number(stats.events[udt::ConnectionStats::Stats::SentACK]).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()), QString::number(stats.events[udt::ConnectionStats::Stats::SentACK]).rightJustified(SERVER_STATS_TABLE_HEADERS[++headerIndex].size()),