OLD | NEW |
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/cubic.h" | 5 #include "net/quic/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/basictypes.h" | |
12 #include "base/logging.h" | 11 #include "base/logging.h" |
13 #include "net/quic/quic_flags.h" | 12 #include "net/quic/quic_flags.h" |
14 #include "net/quic/quic_protocol.h" | 13 #include "net/quic/quic_protocol.h" |
15 #include "net/quic/quic_time.h" | 14 #include "net/quic/quic_time.h" |
16 | 15 |
17 using std::max; | 16 using std::max; |
18 | 17 |
19 namespace net { | 18 namespace net { |
20 | 19 |
21 namespace { | 20 namespace { |
22 | 21 |
23 // Constants based on TCP defaults. | 22 // Constants based on TCP defaults. |
24 // The following constants are in 2^10 fractions of a second instead of ms to | 23 // The following constants are in 2^10 fractions of a second instead of ms to |
25 // allow a 10 shift right to divide. | 24 // allow a 10 shift right to divide. |
26 const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3) | 25 const int kCubeScale = 40; // 1024*1024^3 (first 1024 is from 0.100^3) |
27 // where 0.100 is 100 ms which is the scaling | 26 // where 0.100 is 100 ms which is the scaling |
28 // round trip time. | 27 // round trip time. |
29 const int kCubeCongestionWindowScale = 410; | 28 const int kCubeCongestionWindowScale = 410; |
30 const uint64 kCubeFactor = | 29 const uint64_t kCubeFactor = |
31 (UINT64_C(1) << kCubeScale) / kCubeCongestionWindowScale; | 30 (UINT64_C(1) << kCubeScale) / kCubeCongestionWindowScale; |
32 | 31 |
33 const uint32 kDefaultNumConnections = 2; | 32 const uint32_t kDefaultNumConnections = 2; |
34 const float kBeta = 0.7f; // Default Cubic backoff factor. | 33 const float kBeta = 0.7f; // Default Cubic backoff factor. |
35 // Additional backoff factor when loss occurs in the concave part of the Cubic | 34 // Additional backoff factor when loss occurs in the concave part of the Cubic |
36 // curve. This additional backoff factor is expected to give up bandwidth to | 35 // curve. This additional backoff factor is expected to give up bandwidth to |
37 // new concurrent flows and speed up convergence. | 36 // new concurrent flows and speed up convergence. |
38 const float kBetaLastMax = 0.85f; | 37 const float kBetaLastMax = 0.85f; |
39 | 38 |
40 } // namespace | 39 } // namespace |
41 | 40 |
42 Cubic::Cubic(const QuicClock* clock) | 41 Cubic::Cubic(const QuicClock* clock) |
43 : clock_(clock), | 42 : clock_(clock), |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 if (!epoch_.IsInitialized()) { | 128 if (!epoch_.IsInitialized()) { |
130 // First ACK after a loss event. | 129 // First ACK after a loss event. |
131 epoch_ = current_time; // Start of epoch. | 130 epoch_ = current_time; // Start of epoch. |
132 acked_packets_count_ = 1; // Reset count. | 131 acked_packets_count_ = 1; // Reset count. |
133 // Reset estimated_tcp_congestion_window_ to be in sync with cubic. | 132 // Reset estimated_tcp_congestion_window_ to be in sync with cubic. |
134 estimated_tcp_congestion_window_ = current_congestion_window; | 133 estimated_tcp_congestion_window_ = current_congestion_window; |
135 if (last_max_congestion_window_ <= current_congestion_window) { | 134 if (last_max_congestion_window_ <= current_congestion_window) { |
136 time_to_origin_point_ = 0; | 135 time_to_origin_point_ = 0; |
137 origin_point_congestion_window_ = current_congestion_window; | 136 origin_point_congestion_window_ = current_congestion_window; |
138 } else { | 137 } else { |
139 time_to_origin_point_ = | 138 time_to_origin_point_ = static_cast<uint32_t>( |
140 static_cast<uint32>(cbrt(kCubeFactor * (last_max_congestion_window_ - | 139 cbrt(kCubeFactor * |
141 current_congestion_window))); | 140 (last_max_congestion_window_ - current_congestion_window))); |
142 origin_point_congestion_window_ = last_max_congestion_window_; | 141 origin_point_congestion_window_ = last_max_congestion_window_; |
143 } | 142 } |
144 } else { | 143 } else { |
145 // If sender was app-limited, then freeze congestion window growth during | 144 // If sender was app-limited, then freeze congestion window growth during |
146 // app-limited period. Continue growth now by shifting the epoch-start | 145 // app-limited period. Continue growth now by shifting the epoch-start |
147 // through the app-limited period. | 146 // through the app-limited period. |
148 if (FLAGS_shift_quic_cubic_epoch_when_app_limited && | 147 if (FLAGS_shift_quic_cubic_epoch_when_app_limited && |
149 app_limited_start_time_ != QuicTime::Zero()) { | 148 app_limited_start_time_ != QuicTime::Zero()) { |
150 QuicTime::Delta shift = current_time.Subtract(app_limited_start_time_); | 149 QuicTime::Delta shift = current_time.Subtract(app_limited_start_time_); |
151 DVLOG(1) << "Shifting epoch for quiescence by " << shift.ToMicroseconds(); | 150 DVLOG(1) << "Shifting epoch for quiescence by " << shift.ToMicroseconds(); |
152 epoch_ = epoch_.Add(shift); | 151 epoch_ = epoch_.Add(shift); |
153 app_limited_start_time_ = QuicTime::Zero(); | 152 app_limited_start_time_ = QuicTime::Zero(); |
154 } | 153 } |
155 } | 154 } |
156 | 155 |
157 // Change the time unit from microseconds to 2^10 fractions per second. Take | 156 // Change the time unit from microseconds to 2^10 fractions per second. Take |
158 // the round trip time in account. This is done to allow us to use shift as a | 157 // the round trip time in account. This is done to allow us to use shift as a |
159 // divide operator. | 158 // divide operator. |
160 int64 elapsed_time = | 159 int64_t elapsed_time = |
161 (current_time.Add(delay_min).Subtract(epoch_).ToMicroseconds() << 10) / | 160 (current_time.Add(delay_min).Subtract(epoch_).ToMicroseconds() << 10) / |
162 kNumMicrosPerSecond; | 161 kNumMicrosPerSecond; |
163 | 162 |
164 int64 offset = time_to_origin_point_ - elapsed_time; | 163 int64_t offset = time_to_origin_point_ - elapsed_time; |
165 QuicPacketCount delta_congestion_window = | 164 QuicPacketCount delta_congestion_window = |
166 (kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale; | 165 (kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale; |
167 | 166 |
168 QuicPacketCount target_congestion_window = | 167 QuicPacketCount target_congestion_window = |
169 origin_point_congestion_window_ - delta_congestion_window; | 168 origin_point_congestion_window_ - delta_congestion_window; |
170 | 169 |
171 DCHECK_LT(0u, estimated_tcp_congestion_window_); | 170 DCHECK_LT(0u, estimated_tcp_congestion_window_); |
172 // With dynamic beta/alpha based on number of active streams, it is possible | 171 // With dynamic beta/alpha based on number of active streams, it is possible |
173 // for the required_ack_count to become much lower than acked_packets_count_ | 172 // for the required_ack_count to become much lower than acked_packets_count_ |
174 // suddenly, leading to more than one iteration through the following loop. | 173 // suddenly, leading to more than one iteration through the following loop. |
(...skipping 15 matching lines...) Expand all Loading... |
190 // congestion_window, use highest (fastest). | 189 // congestion_window, use highest (fastest). |
191 if (target_congestion_window < estimated_tcp_congestion_window_) { | 190 if (target_congestion_window < estimated_tcp_congestion_window_) { |
192 target_congestion_window = estimated_tcp_congestion_window_; | 191 target_congestion_window = estimated_tcp_congestion_window_; |
193 } | 192 } |
194 | 193 |
195 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; | 194 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; |
196 return target_congestion_window; | 195 return target_congestion_window; |
197 } | 196 } |
198 | 197 |
199 } // namespace net | 198 } // namespace net |
OLD | NEW |