/***********************************************************
TIMELY Algorithm to compute new rate
************************************************************/
/*
It is assumed this function is part of a 'sender' class, which declares the required instance variables and paramaters as detailed below.
It takes as input the current rate at which data is being sent and the current rtt.
It can be invoked when an ack/completion event is received.
It returns the new rate that can be enforced by the 'sender'.
*/
/* Parameters used and their recommended values (these values may need finetuning based on experimental scenario)
ewma_alpha: recommended value = 0.02
t_low: recommended value = 0 (if using per-packet pacing), 50us (if using per 64KB message pacing)
t_high: recommended value = 1ms
HAI_Thresh: recommended value = 5
additiveIncrement: 10Mbps for 10Gbps line rate
decreaseFactor: 0.8
maxRate = line rate
minRate = optional
*/
/* Other instance variables used and their initialization
prevRTT_: previous RTT (initialized to 0)
negGradientCount_: negative gradient counter for HAI increase (initialized to 0)
avgRTTDiff_: moving average of the RTT difference (initialized to 0)
minRTT_ = fixed minimum network RTT value
last_update_time_: initialized to 0
*/
double getNewRate(double rtt, double rate) {
if(prevRTT_ == 0) prevRTT_ = rtt;
double rtt_diff = rtt - prevRTT_;
if (rtt_diff < 0) {
negGradientCount_++;
} else {
negGradientCount_ = 0;
}
avgRTTDiff_ = ((1 - ewma_alpha) * avgRTTDiff_) + (ewma_alpha * rtt_diff);
double normalized_gradient = avgRTTDiff_ / minRTT_;
double delta_factor = (curTime() - last_update_time_) / minRTT_;
delta_factor = min(delta_factor, 1.0);
prevRTT_ = rtt;
last_update_time_ = curTime();
double new_rate;
if (rtt < t_low) { //additivive increase if rtt < t_low
new_rate = rate + (additiveIncrement * delta_factor);
} else {
if (rtt > t_high) { //multiplicative decrease if rtt > t_high
new_rate = rate * (1 - (delta_factor * decreaseFactor * (1 - (t_high / rtt))));
} else {
if (normalized_gradient <= 0) { //additive increase if avg gradient <= 0
int N = 1;
if (negGradientCount_ >= HAI_thresh) N = 5;
new_rate = rate + (N * additiveIncrement * delta_factor);
} else { //multiplicative decrease if avg gradient > 0
new_rate = rate * (1.0 - (decreaseFactor * normalized_gradient));
}
}
}
//derease in rate capped by 0.5 times the old rate
new_rate = max(new_rate, rate * 0.5);
//enabling max and min cap on the new rate
new_rate = min(new_rate, maxRate);
new_rate = max(new_rate, minRate);
return new_rate;
}