Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(706)

Side by Side Diff: net/quic/congestion_control/hybrid_slow_start.cc

Issue 242593002: Land Recent QUIC Changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Build fix. Use uint32 instead of int Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "net/quic/congestion_control/hybrid_slow_start.h" 5 #include "net/quic/congestion_control/hybrid_slow_start.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "net/quic/congestion_control/rtt_stats.h" 9 #include "net/quic/congestion_control/rtt_stats.h"
10 10
11 using std::max; 11 using std::max;
12 using std::min; 12 using std::min;
13 13
14 namespace net { 14 namespace net {
15 15
16 // Note(pwestin): the magic clamping numbers come from the original code in 16 // Note(pwestin): the magic clamping numbers come from the original code in
17 // tcp_cubic.c. 17 // tcp_cubic.c.
18 const int64 kHybridStartLowWindow = 16; 18 const int64 kHybridStartLowWindow = 16;
19 // Number of delay samples for detecting the increase of delay. 19 // Number of delay samples for detecting the increase of delay.
20 const int kHybridStartMinSamples = 8; 20 const uint32 kHybridStartMinSamples = 8;
21 const int kHybridStartDelayFactorExp = 4; // 2^4 = 16 21 const int kHybridStartDelayFactorExp = 4; // 2^4 = 16
22 const int kHybridStartDelayMinThresholdUs = 2000; 22 const int kHybridStartDelayMinThresholdUs = 2000;
23 // TODO(ianswett): The original paper specifies 8, not 16ms.
23 const int kHybridStartDelayMaxThresholdUs = 16000; 24 const int kHybridStartDelayMaxThresholdUs = 16000;
24 25
25 HybridSlowStart::HybridSlowStart(const QuicClock* clock) 26 HybridSlowStart::HybridSlowStart(const QuicClock* clock)
26 : clock_(clock), 27 : clock_(clock),
27 started_(false), 28 started_(false),
28 found_ack_train_(false), 29 found_ack_train_(false),
29 found_delay_(false), 30 found_delay_(false),
30 round_start_(QuicTime::Zero()), 31 round_start_(QuicTime::Zero()),
31 update_end_sequence_number_(true), 32 update_end_sequence_number_(true),
32 sender_end_sequence_number_(0), 33 sender_end_sequence_number_(0),
33 end_sequence_number_(0), 34 end_sequence_number_(0),
34 last_time_(QuicTime::Zero()), 35 last_close_ack_pair_time_(QuicTime::Zero()),
35 sample_count_(0), 36 rtt_sample_count_(0),
36 current_rtt_(QuicTime::Delta::Zero()) { 37 current_min_rtt_(QuicTime::Delta::Zero()) {
37 } 38 }
38 39
39 void HybridSlowStart::OnPacketAcked( 40 void HybridSlowStart::OnPacketAcked(
40 QuicPacketSequenceNumber acked_sequence_number, bool in_slow_start) { 41 QuicPacketSequenceNumber acked_sequence_number, bool in_slow_start) {
41 if (in_slow_start) { 42 if (in_slow_start && IsEndOfRound(acked_sequence_number)) {
42 if (IsEndOfRound(acked_sequence_number)) { 43 Reset(sender_end_sequence_number_);
43 Reset(sender_end_sequence_number_);
44 }
45 } 44 }
46 45
47 if (sender_end_sequence_number_ == acked_sequence_number) { 46 if (sender_end_sequence_number_ == acked_sequence_number) {
48 DVLOG(1) << "Start update end sequence number @" << acked_sequence_number; 47 DVLOG(1) << "Start update end sequence number @" << acked_sequence_number;
49 update_end_sequence_number_ = true; 48 update_end_sequence_number_ = true;
50 } 49 }
51 } 50 }
52 51
53 void HybridSlowStart::OnPacketSent(QuicPacketSequenceNumber sequence_number, 52 void HybridSlowStart::OnPacketSent(QuicPacketSequenceNumber sequence_number,
54 QuicByteCount available_send_window) { 53 QuicByteCount available_send_window) {
55 if (update_end_sequence_number_) { 54 if (update_end_sequence_number_) {
56 sender_end_sequence_number_ = sequence_number; 55 sender_end_sequence_number_ = sequence_number;
57 if (available_send_window == 0) { 56 if (available_send_window == 0) {
58 update_end_sequence_number_ = false; 57 update_end_sequence_number_ = false;
59 DVLOG(1) << "Stop update end sequence number @" << sequence_number; 58 DVLOG(1) << "Stop update end sequence number @" << sequence_number;
60 } 59 }
61 } 60 }
62 } 61 }
63 62
64 bool HybridSlowStart::ShouldExitSlowStart(const RttStats* rtt_stats, 63 bool HybridSlowStart::ShouldExitSlowStart(const RttStats* rtt_stats,
65 int64 congestion_window) { 64 int64 congestion_window) {
65 // Hybrid start triggers when cwnd is larger than some threshold.
66 if (congestion_window < kHybridStartLowWindow) { 66 if (congestion_window < kHybridStartLowWindow) {
67 return false; 67 return false;
68 } 68 }
69 if (!started()) { 69 if (!started_) {
70 // Time to start the hybrid slow start. 70 // Time to start the hybrid slow start.
71 Reset(sender_end_sequence_number_); 71 Reset(sender_end_sequence_number_);
72 } 72 }
73 Update(rtt_stats->latest_rtt(), rtt_stats->min_rtt()); 73 // TODO(ianswett): Merge UpdateAndMaybeExit into ShouldExitSlowStart in
74 return Exit(); 74 // another refactor CL, since it's only used here.
75 return UpdateAndMaybeExit(rtt_stats->latest_rtt(), rtt_stats->min_rtt());
75 } 76 }
76 77
77 void HybridSlowStart::Restart() { 78 void HybridSlowStart::Restart() {
79 started_ = false;
78 found_ack_train_ = false; 80 found_ack_train_ = false;
79 found_delay_ = false; 81 found_delay_ = false;
80 } 82 }
81 83
82 void HybridSlowStart::Reset(QuicPacketSequenceNumber end_sequence_number) { 84 void HybridSlowStart::Reset(QuicPacketSequenceNumber end_sequence_number) {
83 DVLOG(1) << "Reset hybrid slow start @" << end_sequence_number; 85 DVLOG(1) << "Reset hybrid slow start @" << end_sequence_number;
84 round_start_ = last_time_ = clock_->ApproximateNow(); 86 round_start_ = last_close_ack_pair_time_ = clock_->ApproximateNow();
85 end_sequence_number_ = end_sequence_number; 87 end_sequence_number_ = end_sequence_number;
86 current_rtt_ = QuicTime::Delta::Zero(); 88 current_min_rtt_ = QuicTime::Delta::Zero();
87 sample_count_ = 0; 89 rtt_sample_count_ = 0;
88 started_ = true; 90 started_ = true;
89 } 91 }
90 92
91 bool HybridSlowStart::IsEndOfRound(QuicPacketSequenceNumber ack) const { 93 bool HybridSlowStart::IsEndOfRound(QuicPacketSequenceNumber ack) const {
92 return end_sequence_number_ <= ack; 94 return end_sequence_number_ <= ack;
93 } 95 }
94 96
95 void HybridSlowStart::Update(QuicTime::Delta rtt, QuicTime::Delta delay_min) { 97 bool HybridSlowStart::UpdateAndMaybeExit(QuicTime::Delta rtt,
98 QuicTime::Delta min_rtt) {
96 // The original code doesn't invoke this until we hit 16 packet per burst. 99 // The original code doesn't invoke this until we hit 16 packet per burst.
97 // Since the code handles lower than 16 grecefully and I removed that 100 // Since the code handles lower than 16 gracefully I removed that limit.
98 // limit.
99 if (found_ack_train_ || found_delay_) { 101 if (found_ack_train_ || found_delay_) {
100 return; 102 return true;
101 } 103 }
102 QuicTime current_time = clock_->ApproximateNow(); 104 QuicTime current_time = clock_->ApproximateNow();
103 105
104 // First detection parameter - ack-train detection. 106 // First detection parameter - ack-train detection.
105 // Since slow start burst out packets we can indirectly estimate the inter- 107 // Since slow start burst out packets we can indirectly estimate the inter-
106 // arrival time by looking at the arrival time of the ACKs if the ACKs are 108 // arrival time by looking at the arrival time of the ACKs if the ACKs are
107 // spread out more then half the minimum RTT packets are beeing spread out 109 // spread out more then half the minimum RTT packets are being spread out
108 // more than the capacity. 110 // more than the capacity.
109 // This first trigger will not come into play until we hit roughly 4.8 Mbit/s. 111 // This first trigger will not come into play until we hit roughly 9.6 Mbps
112 // with delayed acks (or 4.8Mbps without delayed acks)
110 // TODO(pwestin): we need to make sure our pacing don't trigger this detector. 113 // TODO(pwestin): we need to make sure our pacing don't trigger this detector.
111 if (current_time.Subtract(last_time_).ToMicroseconds() <= 114 if (current_time.Subtract(last_close_ack_pair_time_).ToMicroseconds() <=
112 kHybridStartDelayMinThresholdUs) { 115 kHybridStartDelayMinThresholdUs) {
113 last_time_ = current_time; 116 last_close_ack_pair_time_ = current_time;
114 if (current_time.Subtract(round_start_).ToMicroseconds() >= 117 found_ack_train_ = current_time.Subtract(round_start_).ToMicroseconds() >=
115 (delay_min.ToMicroseconds() >> 1)) { 118 min_rtt.ToMicroseconds() >> 1;
116 found_ack_train_ = true;
117 }
118 } 119 }
119 // Second detection parameter - delay increase detection. 120 // Second detection parameter - delay increase detection.
120 // Compare the minimum delay (current_rtt_) of the current 121 // Compare the minimum delay (current_min_rtt_) of the current
121 // burst of packets relative to the minimum delay during the session. 122 // burst of packets relative to the minimum delay during the session.
122 // Note: we only look at the first few(8) packets in each burst, since we 123 // Note: we only look at the first few(8) packets in each burst, since we
123 // only want to compare the lowest RTT of the burst relative to previous 124 // only want to compare the lowest RTT of the burst relative to previous
124 // bursts. 125 // bursts.
125 sample_count_++; 126 rtt_sample_count_++;
126 if (sample_count_ <= kHybridStartMinSamples) { 127 if (rtt_sample_count_ <= kHybridStartMinSamples) {
127 if (current_rtt_.IsZero() || current_rtt_ > rtt) { 128 if (current_min_rtt_.IsZero() || current_min_rtt_ > rtt) {
128 current_rtt_ = rtt; 129 current_min_rtt_ = rtt;
129 } 130 }
130 } 131 }
131 // We only need to check this once. 132 // We only need to check this once.
132 if (sample_count_ == kHybridStartMinSamples) { 133 if (rtt_sample_count_ == kHybridStartMinSamples) {
133 int accepted_variance_us = delay_min.ToMicroseconds() >> 134 // Divide min_rtt by 16 to get a rtt increase threshold for exiting.
135 int min_rtt_increase_threshold_us = min_rtt.ToMicroseconds() >>
134 kHybridStartDelayFactorExp; 136 kHybridStartDelayFactorExp;
135 accepted_variance_us = min(accepted_variance_us, 137 // Ensure the rtt threshold is never less than 2ms or more than 16ms.
136 kHybridStartDelayMaxThresholdUs); 138 min_rtt_increase_threshold_us = min(min_rtt_increase_threshold_us,
137 QuicTime::Delta accepted_variance = QuicTime::Delta::FromMicroseconds( 139 kHybridStartDelayMaxThresholdUs);
138 max(accepted_variance_us, kHybridStartDelayMinThresholdUs)); 140 QuicTime::Delta min_rtt_increase_threshold =
141 QuicTime::Delta::FromMicroseconds(max(min_rtt_increase_threshold_us,
142 kHybridStartDelayMinThresholdUs));
139 143
140 if (current_rtt_ > delay_min.Add(accepted_variance)) { 144 found_delay_ = current_min_rtt_ > min_rtt.Add(min_rtt_increase_threshold);
141 found_delay_ = true;
142 }
143 } 145 }
144 } 146 // If either of the two conditions are met we exit from slow start.
145 147 return found_ack_train_ || found_delay_;
146 bool HybridSlowStart::Exit() {
147 // If either one of the two conditions are met we exit from slow start
148 // immediately.
149 if (found_ack_train_ || found_delay_) {
150 return true;
151 }
152 return false;
153 } 148 }
154 149
155 } // namespace net 150 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/hybrid_slow_start.h ('k') | net/quic/congestion_control/hybrid_slow_start_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698