| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 #include "net/quic/congestion_control/hybrid_slow_start.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 | |
| 9 using std::max; | |
| 10 using std::min; | |
| 11 | |
| 12 namespace net { | |
| 13 | |
| 14 // Note(pwestin): the magic clamping numbers come from the original code in | |
| 15 // tcp_cubic.c. | |
| 16 const int64_t kHybridStartLowWindow = 16; | |
| 17 // Number of delay samples for detecting the increase of delay. | |
| 18 const uint32_t kHybridStartMinSamples = 8; | |
| 19 // Exit slow start if the min rtt has increased by more than 1/8th. | |
| 20 const int kHybridStartDelayFactorExp = 3; // 2^3 = 8 | |
| 21 // The original paper specifies 2 and 8ms, but those have changed over time. | |
| 22 const int64_t kHybridStartDelayMinThresholdUs = 4000; | |
| 23 const int64_t kHybridStartDelayMaxThresholdUs = 16000; | |
| 24 | |
| 25 HybridSlowStart::HybridSlowStart() | |
| 26 : started_(false), | |
| 27 hystart_found_(NOT_FOUND), | |
| 28 last_sent_packet_number_(0), | |
| 29 end_packet_number_(0), | |
| 30 rtt_sample_count_(0), | |
| 31 current_min_rtt_(QuicTime::Delta::Zero()) {} | |
| 32 | |
| 33 void HybridSlowStart::OnPacketAcked(QuicPacketNumber acked_packet_number) { | |
| 34 // OnPacketAcked gets invoked after ShouldExitSlowStart, so it's best to end | |
| 35 // the round when the final packet of the burst is received and start it on | |
| 36 // the next incoming ack. | |
| 37 if (IsEndOfRound(acked_packet_number)) { | |
| 38 started_ = false; | |
| 39 } | |
| 40 } | |
| 41 | |
| 42 void HybridSlowStart::OnPacketSent(QuicPacketNumber packet_number) { | |
| 43 last_sent_packet_number_ = packet_number; | |
| 44 } | |
| 45 | |
| 46 void HybridSlowStart::Restart() { | |
| 47 started_ = false; | |
| 48 hystart_found_ = NOT_FOUND; | |
| 49 } | |
| 50 | |
| 51 void HybridSlowStart::StartReceiveRound(QuicPacketNumber last_sent) { | |
| 52 DVLOG(1) << "Reset hybrid slow start @" << last_sent; | |
| 53 end_packet_number_ = last_sent; | |
| 54 current_min_rtt_ = QuicTime::Delta::Zero(); | |
| 55 rtt_sample_count_ = 0; | |
| 56 started_ = true; | |
| 57 } | |
| 58 | |
| 59 bool HybridSlowStart::IsEndOfRound(QuicPacketNumber ack) const { | |
| 60 return end_packet_number_ <= ack; | |
| 61 } | |
| 62 | |
| 63 bool HybridSlowStart::ShouldExitSlowStart(QuicTime::Delta latest_rtt, | |
| 64 QuicTime::Delta min_rtt, | |
| 65 QuicPacketCount congestion_window) { | |
| 66 if (!started_) { | |
| 67 // Time to start the hybrid slow start. | |
| 68 StartReceiveRound(last_sent_packet_number_); | |
| 69 } | |
| 70 if (hystart_found_ != NOT_FOUND) { | |
| 71 return true; | |
| 72 } | |
| 73 // Second detection parameter - delay increase detection. | |
| 74 // Compare the minimum delay (current_min_rtt_) of the current | |
| 75 // burst of packets relative to the minimum delay during the session. | |
| 76 // Note: we only look at the first few(8) packets in each burst, since we | |
| 77 // only want to compare the lowest RTT of the burst relative to previous | |
| 78 // bursts. | |
| 79 rtt_sample_count_++; | |
| 80 if (rtt_sample_count_ <= kHybridStartMinSamples) { | |
| 81 if (current_min_rtt_.IsZero() || current_min_rtt_ > latest_rtt) { | |
| 82 current_min_rtt_ = latest_rtt; | |
| 83 } | |
| 84 } | |
| 85 // We only need to check this once per round. | |
| 86 if (rtt_sample_count_ == kHybridStartMinSamples) { | |
| 87 // Divide min_rtt by 8 to get a rtt increase threshold for exiting. | |
| 88 int64_t min_rtt_increase_threshold_us = | |
| 89 min_rtt.ToMicroseconds() >> kHybridStartDelayFactorExp; | |
| 90 // Ensure the rtt threshold is never less than 2ms or more than 16ms. | |
| 91 min_rtt_increase_threshold_us = | |
| 92 min(min_rtt_increase_threshold_us, kHybridStartDelayMaxThresholdUs); | |
| 93 QuicTime::Delta min_rtt_increase_threshold = | |
| 94 QuicTime::Delta::FromMicroseconds(max(min_rtt_increase_threshold_us, | |
| 95 kHybridStartDelayMinThresholdUs)); | |
| 96 | |
| 97 if (current_min_rtt_ > min_rtt + min_rtt_increase_threshold) { | |
| 98 hystart_found_ = DELAY; | |
| 99 } | |
| 100 } | |
| 101 // Exit from slow start if the cwnd is greater than 16 and | |
| 102 // increasing delay is found. | |
| 103 return congestion_window >= kHybridStartLowWindow && | |
| 104 hystart_found_ != NOT_FOUND; | |
| 105 } | |
| 106 | |
| 107 } // namespace net | |
| OLD | NEW |