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 |