Index: net/quic/congestion_control/hybrid_slow_start.cc |
diff --git a/net/quic/congestion_control/hybrid_slow_start.cc b/net/quic/congestion_control/hybrid_slow_start.cc |
index 9325ca4590e0a975b92391d22a8276fd535a61c8..284d1bca3bc0912f04b8c7e02aebdc7878c6cb8c 100644 |
--- a/net/quic/congestion_control/hybrid_slow_start.cc |
+++ b/net/quic/congestion_control/hybrid_slow_start.cc |
@@ -17,9 +17,10 @@ namespace net { |
// tcp_cubic.c. |
const int64 kHybridStartLowWindow = 16; |
// Number of delay samples for detecting the increase of delay. |
-const int kHybridStartMinSamples = 8; |
+const uint32 kHybridStartMinSamples = 8; |
const int kHybridStartDelayFactorExp = 4; // 2^4 = 16 |
const int kHybridStartDelayMinThresholdUs = 2000; |
+// TODO(ianswett): The original paper specifies 8, not 16ms. |
const int kHybridStartDelayMaxThresholdUs = 16000; |
HybridSlowStart::HybridSlowStart(const QuicClock* clock) |
@@ -31,17 +32,15 @@ HybridSlowStart::HybridSlowStart(const QuicClock* clock) |
update_end_sequence_number_(true), |
sender_end_sequence_number_(0), |
end_sequence_number_(0), |
- last_time_(QuicTime::Zero()), |
- sample_count_(0), |
- current_rtt_(QuicTime::Delta::Zero()) { |
+ last_close_ack_pair_time_(QuicTime::Zero()), |
+ rtt_sample_count_(0), |
+ current_min_rtt_(QuicTime::Delta::Zero()) { |
} |
void HybridSlowStart::OnPacketAcked( |
QuicPacketSequenceNumber acked_sequence_number, bool in_slow_start) { |
- if (in_slow_start) { |
- if (IsEndOfRound(acked_sequence_number)) { |
- Reset(sender_end_sequence_number_); |
- } |
+ if (in_slow_start && IsEndOfRound(acked_sequence_number)) { |
+ Reset(sender_end_sequence_number_); |
} |
if (sender_end_sequence_number_ == acked_sequence_number) { |
@@ -63,28 +62,31 @@ void HybridSlowStart::OnPacketSent(QuicPacketSequenceNumber sequence_number, |
bool HybridSlowStart::ShouldExitSlowStart(const RttStats* rtt_stats, |
int64 congestion_window) { |
+ // Hybrid start triggers when cwnd is larger than some threshold. |
if (congestion_window < kHybridStartLowWindow) { |
return false; |
} |
- if (!started()) { |
+ if (!started_) { |
// Time to start the hybrid slow start. |
Reset(sender_end_sequence_number_); |
} |
- Update(rtt_stats->latest_rtt(), rtt_stats->min_rtt()); |
- return Exit(); |
+ // TODO(ianswett): Merge UpdateAndMaybeExit into ShouldExitSlowStart in |
+ // another refactor CL, since it's only used here. |
+ return UpdateAndMaybeExit(rtt_stats->latest_rtt(), rtt_stats->min_rtt()); |
} |
void HybridSlowStart::Restart() { |
+ started_ = false; |
found_ack_train_ = false; |
found_delay_ = false; |
} |
void HybridSlowStart::Reset(QuicPacketSequenceNumber end_sequence_number) { |
DVLOG(1) << "Reset hybrid slow start @" << end_sequence_number; |
- round_start_ = last_time_ = clock_->ApproximateNow(); |
+ round_start_ = last_close_ack_pair_time_ = clock_->ApproximateNow(); |
end_sequence_number_ = end_sequence_number; |
- current_rtt_ = QuicTime::Delta::Zero(); |
- sample_count_ = 0; |
+ current_min_rtt_ = QuicTime::Delta::Zero(); |
+ rtt_sample_count_ = 0; |
started_ = true; |
} |
@@ -92,64 +94,57 @@ bool HybridSlowStart::IsEndOfRound(QuicPacketSequenceNumber ack) const { |
return end_sequence_number_ <= ack; |
} |
-void HybridSlowStart::Update(QuicTime::Delta rtt, QuicTime::Delta delay_min) { |
+bool HybridSlowStart::UpdateAndMaybeExit(QuicTime::Delta rtt, |
+ QuicTime::Delta min_rtt) { |
// The original code doesn't invoke this until we hit 16 packet per burst. |
- // Since the code handles lower than 16 grecefully and I removed that |
- // limit. |
+ // Since the code handles lower than 16 gracefully I removed that limit. |
if (found_ack_train_ || found_delay_) { |
- return; |
+ return true; |
} |
QuicTime current_time = clock_->ApproximateNow(); |
// First detection parameter - ack-train detection. |
// Since slow start burst out packets we can indirectly estimate the inter- |
// arrival time by looking at the arrival time of the ACKs if the ACKs are |
- // spread out more then half the minimum RTT packets are beeing spread out |
+ // spread out more then half the minimum RTT packets are being spread out |
// more than the capacity. |
- // This first trigger will not come into play until we hit roughly 4.8 Mbit/s. |
+ // This first trigger will not come into play until we hit roughly 9.6 Mbps |
+ // with delayed acks (or 4.8Mbps without delayed acks) |
// TODO(pwestin): we need to make sure our pacing don't trigger this detector. |
- if (current_time.Subtract(last_time_).ToMicroseconds() <= |
- kHybridStartDelayMinThresholdUs) { |
- last_time_ = current_time; |
- if (current_time.Subtract(round_start_).ToMicroseconds() >= |
- (delay_min.ToMicroseconds() >> 1)) { |
- found_ack_train_ = true; |
- } |
+ if (current_time.Subtract(last_close_ack_pair_time_).ToMicroseconds() <= |
+ kHybridStartDelayMinThresholdUs) { |
+ last_close_ack_pair_time_ = current_time; |
+ found_ack_train_ = current_time.Subtract(round_start_).ToMicroseconds() >= |
+ min_rtt.ToMicroseconds() >> 1; |
} |
// Second detection parameter - delay increase detection. |
- // Compare the minimum delay (current_rtt_) of the current |
+ // Compare the minimum delay (current_min_rtt_) of the current |
// burst of packets relative to the minimum delay during the session. |
// Note: we only look at the first few(8) packets in each burst, since we |
// only want to compare the lowest RTT of the burst relative to previous |
// bursts. |
- sample_count_++; |
- if (sample_count_ <= kHybridStartMinSamples) { |
- if (current_rtt_.IsZero() || current_rtt_ > rtt) { |
- current_rtt_ = rtt; |
+ rtt_sample_count_++; |
+ if (rtt_sample_count_ <= kHybridStartMinSamples) { |
+ if (current_min_rtt_.IsZero() || current_min_rtt_ > rtt) { |
+ current_min_rtt_ = rtt; |
} |
} |
// We only need to check this once. |
- if (sample_count_ == kHybridStartMinSamples) { |
- int accepted_variance_us = delay_min.ToMicroseconds() >> |
+ if (rtt_sample_count_ == kHybridStartMinSamples) { |
+ // Divide min_rtt by 16 to get a rtt increase threshold for exiting. |
+ int min_rtt_increase_threshold_us = min_rtt.ToMicroseconds() >> |
kHybridStartDelayFactorExp; |
- accepted_variance_us = min(accepted_variance_us, |
- kHybridStartDelayMaxThresholdUs); |
- QuicTime::Delta accepted_variance = QuicTime::Delta::FromMicroseconds( |
- max(accepted_variance_us, kHybridStartDelayMinThresholdUs)); |
- |
- if (current_rtt_ > delay_min.Add(accepted_variance)) { |
- found_delay_ = true; |
- } |
- } |
-} |
- |
-bool HybridSlowStart::Exit() { |
- // If either one of the two conditions are met we exit from slow start |
- // immediately. |
- if (found_ack_train_ || found_delay_) { |
- return true; |
+ // Ensure the rtt threshold is never less than 2ms or more than 16ms. |
+ min_rtt_increase_threshold_us = min(min_rtt_increase_threshold_us, |
+ kHybridStartDelayMaxThresholdUs); |
+ QuicTime::Delta min_rtt_increase_threshold = |
+ QuicTime::Delta::FromMicroseconds(max(min_rtt_increase_threshold_us, |
+ kHybridStartDelayMinThresholdUs)); |
+ |
+ found_delay_ = current_min_rtt_ > min_rtt.Add(min_rtt_increase_threshold); |
} |
- return false; |
+ // If either of the two conditions are met we exit from slow start. |
+ return found_ack_train_ || found_delay_; |
} |
} // namespace net |