This source file includes following definitions.
- estimated_congestion_delay_
- OnAcknowledgedPacket
- UpdateSendReceiveTimeOffset
- GetState
- UpdateFilter
- UpdateDeltaEstimate
- DetectDrift
- DetectSlope
#include "net/quic/congestion_control/inter_arrival_overuse_detector.h"
#include <math.h>
#include <stdlib.h>
#include <algorithm>
using std::max;
static const float kInitialVarianceNoise = 1000000.0;
static const int kMinVarianceDelta = 10000;
static const int kThresholdAccumulatedDeltasUs = 1000;
static const int kBetaNumerator = 49;
static const int kBetaDenominator = 50;
static const int kDetectDriftStandardDeviation = 5;
static const float kDetectTimeDiffStandardDeviation = 7;
static const int kDetectSlopeFactor = 14;
static const int kMinSamplesBeforeDetect = 10;
namespace net {
InterArrivalOveruseDetector::InterArrivalOveruseDetector()
: last_sequence_number_(0),
num_of_deltas_(0),
accumulated_deltas_(QuicTime::Delta::Zero()),
delta_mean_(0.0),
delta_variance_(kInitialVarianceNoise),
delta_overuse_counter_(0),
delta_estimate_(kBandwidthSteady),
slope_overuse_counter_(0),
slope_estimate_(kBandwidthSteady),
send_receive_offset_(QuicTime::Delta::Infinite()),
estimated_congestion_delay_(QuicTime::Delta::Zero()) {
}
void InterArrivalOveruseDetector::OnAcknowledgedPacket(
QuicPacketSequenceNumber sequence_number,
QuicTime send_time,
bool last_of_send_time,
QuicTime receive_time) {
if (last_sequence_number_ >= sequence_number) {
DVLOG(1) << "Skip old packet";
return;
}
last_sequence_number_ = sequence_number;
if (current_packet_group_.send_time != send_time) {
current_packet_group_.send_time = send_time;
UpdateSendReceiveTimeOffset(receive_time.Subtract(send_time));
}
if (!last_of_send_time) {
return;
}
if (previous_packet_group_.send_time.IsInitialized()) {
QuicTime::Delta sent_delta = send_time.Subtract(
previous_packet_group_.send_time);
QuicTime::Delta receive_delta = receive_time.Subtract(
previous_packet_group_.last_receive_time);
UpdateFilter(receive_delta, sent_delta);
}
previous_packet_group_ = current_packet_group_;
previous_packet_group_.last_receive_time = receive_time;
}
void InterArrivalOveruseDetector::UpdateSendReceiveTimeOffset(
QuicTime::Delta offset) {
if (offset.ToMicroseconds() < send_receive_offset_.ToMicroseconds()) {
send_receive_offset_ = offset;
}
estimated_congestion_delay_ = offset.Subtract(send_receive_offset_);
}
BandwidthUsage InterArrivalOveruseDetector::GetState(
QuicTime::Delta* estimated_congestion_delay) {
*estimated_congestion_delay = estimated_congestion_delay_;
int64 sigma_delta = sqrt(static_cast<double>(delta_variance_));
DetectSlope(sigma_delta);
DetectDrift(sigma_delta);
return max(slope_estimate_, delta_estimate_);
}
void InterArrivalOveruseDetector::UpdateFilter(QuicTime::Delta received_delta,
QuicTime::Delta sent_delta) {
++num_of_deltas_;
QuicTime::Delta time_diff = received_delta.Subtract(sent_delta);
UpdateDeltaEstimate(time_diff);
accumulated_deltas_ = accumulated_deltas_.Add(time_diff);
}
void InterArrivalOveruseDetector::UpdateDeltaEstimate(
QuicTime::Delta residual) {
DCHECK_EQ(1, kBetaDenominator - kBetaNumerator);
int64 residual_us = residual.ToMicroseconds();
delta_mean_ =
(kBetaNumerator * delta_mean_ + residual_us) / kBetaDenominator;
delta_variance_ =
(kBetaNumerator * delta_variance_ +
(delta_mean_ - residual_us) * (delta_mean_ - residual_us)) /
kBetaDenominator;
if (delta_variance_ < kMinVarianceDelta) {
delta_variance_ = kMinVarianceDelta;
}
}
void InterArrivalOveruseDetector::DetectDrift(int64 sigma_delta) {
if (num_of_deltas_ < kMinSamplesBeforeDetect) {
return;
}
if (delta_overuse_counter_ > 0 &&
accumulated_deltas_.ToMicroseconds() > kThresholdAccumulatedDeltasUs) {
if (delta_estimate_ != kBandwidthDraining) {
DVLOG(1) << "Bandwidth estimate drift: Draining buffer(s) "
<< accumulated_deltas_.ToMilliseconds() << " ms";
delta_estimate_ = kBandwidthDraining;
}
return;
}
if ((sigma_delta * kDetectTimeDiffStandardDeviation >
estimated_congestion_delay_.ToMicroseconds()) &&
(sigma_delta * kDetectDriftStandardDeviation >
std::abs(accumulated_deltas_.ToMicroseconds()))) {
if (delta_estimate_ != kBandwidthSteady) {
DVLOG(1) << "Bandwidth estimate drift: Steady"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta
<< " offset:" << send_receive_offset_.ToMicroseconds()
<< " delta:" << estimated_congestion_delay_.ToMicroseconds()
<< " drift:" << accumulated_deltas_.ToMicroseconds();
delta_estimate_ = kBandwidthSteady;
accumulated_deltas_ = QuicTime::Delta::Zero();
delta_overuse_counter_ = 0;
}
return;
}
if (accumulated_deltas_.ToMicroseconds() > 0) {
if (delta_estimate_ != kBandwidthOverUsing) {
++delta_overuse_counter_;
DVLOG(1) << "Bandwidth estimate drift: Over using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta
<< " offset:" << send_receive_offset_.ToMicroseconds()
<< " delta:" << estimated_congestion_delay_.ToMicroseconds()
<< " drift:" << accumulated_deltas_.ToMicroseconds();
delta_estimate_ = kBandwidthOverUsing;
}
} else {
if (delta_estimate_ != kBandwidthUnderUsing) {
--delta_overuse_counter_;
DVLOG(1) << "Bandwidth estimate drift: Under using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta
<< " offset:" << send_receive_offset_.ToMicroseconds()
<< " delta:" << estimated_congestion_delay_.ToMicroseconds()
<< " drift:" << accumulated_deltas_.ToMicroseconds();
delta_estimate_ = kBandwidthUnderUsing;
}
accumulated_deltas_ = accumulated_deltas_.Add(
QuicTime::Delta::FromMicroseconds(sigma_delta >> 3));
}
}
void InterArrivalOveruseDetector::DetectSlope(int64 sigma_delta) {
if (num_of_deltas_ < kMinSamplesBeforeDetect) {
return;
}
if (slope_overuse_counter_ > 0 && delta_mean_ > 0) {
if (slope_estimate_ != kBandwidthDraining) {
DVLOG(1) << "Bandwidth estimate slope: Draining buffer(s)";
}
slope_estimate_ = kBandwidthDraining;
return;
}
if (sigma_delta > abs(delta_mean_) * kDetectSlopeFactor) {
if (slope_estimate_ != kBandwidthSteady) {
DVLOG(1) << "Bandwidth estimate slope: Steady"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta;
slope_overuse_counter_ = 0;
slope_estimate_ = kBandwidthSteady;
}
return;
}
if (delta_mean_ > 0) {
if (slope_estimate_ != kBandwidthOverUsing) {
++slope_overuse_counter_;
DVLOG(1) << "Bandwidth estimate slope: Over using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta;
slope_estimate_ = kBandwidthOverUsing;
}
} else {
if (slope_estimate_ != kBandwidthUnderUsing) {
--slope_overuse_counter_;
DVLOG(1) << "Bandwidth estimate slope: Under using"
<< " mean:" << delta_mean_
<< " sigma:" << sigma_delta;
slope_estimate_ = kBandwidthUnderUsing;
}
}
}
}