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

Side by Side Diff: net/quic/core/congestion_control/cubic.cc

Issue 2351963005: Limit QUIC's Cubic CWND increases to 1/2 the bytes acked when in (Closed)
Patch Set: Created 4 years, 3 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
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/core/congestion_control/cubic.h" 5 #include "net/quic/core/congestion_control/cubic.h"
6 6
7 #include <stdint.h> 7 #include <stdint.h>
8 #include <algorithm> 8 #include <algorithm>
9 #include <cmath> 9 #include <cmath>
10 10
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "net/quic/core/quic_flags.h" 12 #include "net/quic/core/quic_flags.h"
13 #include "net/quic/core/quic_protocol.h" 13 #include "net/quic/core/quic_protocol.h"
14 #include "net/quic/core/quic_time.h" 14 #include "net/quic/core/quic_time.h"
15 15
16 using std::max; 16 using std::max;
17 using std::min;
17 18
18 namespace net { 19 namespace net {
19 20
20 namespace { 21 namespace {
21 22
22 // Constants based on TCP defaults. 23 // Constants based on TCP defaults.
23 // The following constants are in 2^10 fractions of a second instead of ms to 24 // The following constants are in 2^10 fractions of a second instead of ms to
24 // allow a 10 shift right to divide. 25 // allow a 10 shift right to divide.
25 const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3) 26 const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3)
26 // where 0.100 is 100 ms which is the scaling 27 // where 0.100 is 100 ms which is the scaling
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 return (num_connections_ - 1 + kBeta) / num_connections_; 68 return (num_connections_ - 1 + kBeta) / num_connections_;
68 } 69 }
69 70
70 void Cubic::Reset() { 71 void Cubic::Reset() {
71 epoch_ = QuicTime::Zero(); // Reset time. 72 epoch_ = QuicTime::Zero(); // Reset time.
72 app_limited_start_time_ = QuicTime::Zero(); 73 app_limited_start_time_ = QuicTime::Zero();
73 last_update_time_ = QuicTime::Zero(); // Reset time. 74 last_update_time_ = QuicTime::Zero(); // Reset time.
74 last_congestion_window_ = 0; 75 last_congestion_window_ = 0;
75 last_max_congestion_window_ = 0; 76 last_max_congestion_window_ = 0;
76 acked_packets_count_ = 0; 77 acked_packets_count_ = 0;
78 epoch_packets_count_ = 0;
77 estimated_tcp_congestion_window_ = 0; 79 estimated_tcp_congestion_window_ = 0;
78 origin_point_congestion_window_ = 0; 80 origin_point_congestion_window_ = 0;
79 time_to_origin_point_ = 0; 81 time_to_origin_point_ = 0;
80 last_target_congestion_window_ = 0; 82 last_target_congestion_window_ = 0;
81 } 83 }
82 84
83 void Cubic::OnApplicationLimited() { 85 void Cubic::OnApplicationLimited() {
84 // When sender is not using the available congestion window, Cubic's epoch 86 // When sender is not using the available congestion window, Cubic's epoch
85 // should not continue growing. Reset the epoch when in such a period. 87 // should not continue growing. Reset the epoch when in such a period.
86 epoch_ = QuicTime::Zero(); 88 epoch_ = QuicTime::Zero();
(...skipping 10 matching lines...) Expand all
97 last_max_congestion_window_ = current_congestion_window; 99 last_max_congestion_window_ = current_congestion_window;
98 } 100 }
99 epoch_ = QuicTime::Zero(); // Reset time. 101 epoch_ = QuicTime::Zero(); // Reset time.
100 return static_cast<int>(current_congestion_window * Beta()); 102 return static_cast<int>(current_congestion_window * Beta());
101 } 103 }
102 104
103 QuicPacketCount Cubic::CongestionWindowAfterAck( 105 QuicPacketCount Cubic::CongestionWindowAfterAck(
104 QuicPacketCount current_congestion_window, 106 QuicPacketCount current_congestion_window,
105 QuicTime::Delta delay_min) { 107 QuicTime::Delta delay_min) {
106 acked_packets_count_ += 1; // Packets acked. 108 acked_packets_count_ += 1; // Packets acked.
109 epoch_packets_count_ += 1;
107 QuicTime current_time = clock_->ApproximateNow(); 110 QuicTime current_time = clock_->ApproximateNow();
108 111
109 // Cubic is "independent" of RTT, the update is limited by the time elapsed. 112 // Cubic is "independent" of RTT, the update is limited by the time elapsed.
110 if (last_congestion_window_ == current_congestion_window && 113 if (last_congestion_window_ == current_congestion_window &&
111 (current_time - last_update_time_ <= MaxCubicTimeInterval())) { 114 (current_time - last_update_time_ <= MaxCubicTimeInterval())) {
112 return max(last_target_congestion_window_, 115 return max(last_target_congestion_window_,
113 estimated_tcp_congestion_window_); 116 estimated_tcp_congestion_window_);
114 } 117 }
115 last_congestion_window_ = current_congestion_window; 118 last_congestion_window_ = current_congestion_window;
116 last_update_time_ = current_time; 119 last_update_time_ = current_time;
117 120
118 if (!epoch_.IsInitialized()) { 121 if (!epoch_.IsInitialized()) {
119 // First ACK after a loss event. 122 // First ACK after a loss event.
120 epoch_ = current_time; // Start of epoch. 123 epoch_ = current_time; // Start of epoch.
121 acked_packets_count_ = 1; // Reset count. 124 acked_packets_count_ = 1; // Reset count.
125 epoch_packets_count_ = 1;
122 // Reset estimated_tcp_congestion_window_ to be in sync with cubic. 126 // Reset estimated_tcp_congestion_window_ to be in sync with cubic.
123 estimated_tcp_congestion_window_ = current_congestion_window; 127 estimated_tcp_congestion_window_ = current_congestion_window;
124 if (last_max_congestion_window_ <= current_congestion_window) { 128 if (last_max_congestion_window_ <= current_congestion_window) {
125 time_to_origin_point_ = 0; 129 time_to_origin_point_ = 0;
126 origin_point_congestion_window_ = current_congestion_window; 130 origin_point_congestion_window_ = current_congestion_window;
127 } else { 131 } else {
128 time_to_origin_point_ = static_cast<uint32_t>( 132 time_to_origin_point_ = static_cast<uint32_t>(
129 cbrt(kCubeFactor * 133 cbrt(kCubeFactor *
130 (last_max_congestion_window_ - current_congestion_window))); 134 (last_max_congestion_window_ - current_congestion_window)));
131 origin_point_congestion_window_ = last_max_congestion_window_; 135 origin_point_congestion_window_ = last_max_congestion_window_;
132 } 136 }
133 } 137 }
134 138
135 // Change the time unit from microseconds to 2^10 fractions per second. Take 139 // Change the time unit from microseconds to 2^10 fractions per second. Take
136 // the round trip time in account. This is done to allow us to use shift as a 140 // the round trip time in account. This is done to allow us to use shift as a
137 // divide operator. 141 // divide operator.
138 int64_t elapsed_time = 142 int64_t elapsed_time =
139 ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / 143 ((current_time + delay_min - epoch_).ToMicroseconds() << 10) /
140 kNumMicrosPerSecond; 144 kNumMicrosPerSecond;
141 145
142 int64_t offset = time_to_origin_point_ - elapsed_time; 146 int64_t offset = time_to_origin_point_ - elapsed_time;
143 QuicPacketCount delta_congestion_window = 147 QuicPacketCount delta_congestion_window =
144 (kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale; 148 (kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale;
145 149
146 QuicPacketCount target_congestion_window = 150 QuicPacketCount target_congestion_window =
147 origin_point_congestion_window_ - delta_congestion_window; 151 origin_point_congestion_window_ - delta_congestion_window;
148 152
153 if (FLAGS_quic_limit_cubic_cwnd_increase) {
154 // Limit the CWND increase to half the acked packets rounded up to the
155 // nearest packet.
156 target_congestion_window =
157 min(target_congestion_window,
158 current_congestion_window + (epoch_packets_count_ + 1) / 2);
159 }
160
149 DCHECK_LT(0u, estimated_tcp_congestion_window_); 161 DCHECK_LT(0u, estimated_tcp_congestion_window_);
150 // With dynamic beta/alpha based on number of active streams, it is possible 162 // With dynamic beta/alpha based on number of active streams, it is possible
151 // for the required_ack_count to become much lower than acked_packets_count_ 163 // for the required_ack_count to become much lower than acked_packets_count_
152 // suddenly, leading to more than one iteration through the following loop. 164 // suddenly, leading to more than one iteration through the following loop.
153 while (true) { 165 while (true) {
154 // Update estimated TCP congestion_window. 166 // Update estimated TCP congestion_window.
155 QuicPacketCount required_ack_count = static_cast<QuicPacketCount>( 167 QuicPacketCount required_ack_count = static_cast<QuicPacketCount>(
156 estimated_tcp_congestion_window_ / Alpha()); 168 estimated_tcp_congestion_window_ / Alpha());
157 if (acked_packets_count_ < required_ack_count) { 169 if (acked_packets_count_ < required_ack_count) {
158 break; 170 break;
159 } 171 }
160 acked_packets_count_ -= required_ack_count; 172 acked_packets_count_ -= required_ack_count;
161 estimated_tcp_congestion_window_++; 173 estimated_tcp_congestion_window_++;
162 } 174 }
175 epoch_packets_count_ = 0;
163 176
164 // We have a new cubic congestion window. 177 // We have a new cubic congestion window.
165 last_target_congestion_window_ = target_congestion_window; 178 last_target_congestion_window_ = target_congestion_window;
166 179
167 // Compute target congestion_window based on cubic target and estimated TCP 180 // Compute target congestion_window based on cubic target and estimated TCP
168 // congestion_window, use highest (fastest). 181 // congestion_window, use highest (fastest).
169 if (target_congestion_window < estimated_tcp_congestion_window_) { 182 if (target_congestion_window < estimated_tcp_congestion_window_) {
170 target_congestion_window = estimated_tcp_congestion_window_; 183 target_congestion_window = estimated_tcp_congestion_window_;
171 } 184 }
172 185
173 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; 186 DVLOG(1) << "Final target congestion_window: " << target_congestion_window;
174 return target_congestion_window; 187 return target_congestion_window;
175 } 188 }
176 189
177 } // namespace net 190 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/core/congestion_control/cubic.h ('k') | net/quic/core/congestion_control/cubic_bytes.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698