| 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/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 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 37 // new concurrent flows and speed up convergence. | 37 // new concurrent flows and speed up convergence. |
| 38 const float kBetaLastMax = 0.85f; | 38 const float kBetaLastMax = 0.85f; |
| 39 | 39 |
| 40 } // namespace | 40 } // namespace |
| 41 | 41 |
| 42 Cubic::Cubic(const QuicClock* clock) | 42 Cubic::Cubic(const QuicClock* clock) |
| 43 : clock_(clock), | 43 : clock_(clock), |
| 44 num_connections_(kDefaultNumConnections), | 44 num_connections_(kDefaultNumConnections), |
| 45 epoch_(QuicTime::Zero()), | 45 epoch_(QuicTime::Zero()), |
| 46 app_limited_start_time_(QuicTime::Zero()), | 46 app_limited_start_time_(QuicTime::Zero()), |
| 47 last_update_time_(QuicTime::Zero()) { | 47 last_update_time_(QuicTime::Zero()), |
| 48 fix_convex_mode_(false) { |
| 48 Reset(); | 49 Reset(); |
| 49 } | 50 } |
| 50 | 51 |
| 51 void Cubic::SetNumConnections(int num_connections) { | 52 void Cubic::SetNumConnections(int num_connections) { |
| 52 num_connections_ = num_connections; | 53 num_connections_ = num_connections; |
| 53 } | 54 } |
| 54 | 55 |
| 55 float Cubic::Alpha() const { | 56 float Cubic::Alpha() const { |
| 56 // TCPFriendly alpha is described in Section 3.3 of the CUBIC paper. Note that | 57 // TCPFriendly alpha is described in Section 3.3 of the CUBIC paper. Note that |
| 57 // beta here is a cwnd multiplier, and is equal to 1-beta from the paper. | 58 // beta here is a cwnd multiplier, and is equal to 1-beta from the paper. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 73 app_limited_start_time_ = QuicTime::Zero(); | 74 app_limited_start_time_ = QuicTime::Zero(); |
| 74 last_update_time_ = QuicTime::Zero(); // Reset time. | 75 last_update_time_ = QuicTime::Zero(); // Reset time. |
| 75 last_congestion_window_ = 0; | 76 last_congestion_window_ = 0; |
| 76 last_max_congestion_window_ = 0; | 77 last_max_congestion_window_ = 0; |
| 77 acked_packets_count_ = 0; | 78 acked_packets_count_ = 0; |
| 78 epoch_packets_count_ = 0; | 79 epoch_packets_count_ = 0; |
| 79 estimated_tcp_congestion_window_ = 0; | 80 estimated_tcp_congestion_window_ = 0; |
| 80 origin_point_congestion_window_ = 0; | 81 origin_point_congestion_window_ = 0; |
| 81 time_to_origin_point_ = 0; | 82 time_to_origin_point_ = 0; |
| 82 last_target_congestion_window_ = 0; | 83 last_target_congestion_window_ = 0; |
| 84 fix_convex_mode_ = false; |
| 83 } | 85 } |
| 84 | 86 |
| 85 void Cubic::OnApplicationLimited() { | 87 void Cubic::OnApplicationLimited() { |
| 86 // When sender is not using the available congestion window, Cubic's epoch | 88 // When sender is not using the available congestion window, Cubic's epoch |
| 87 // should not continue growing. Reset the epoch when in such a period. | 89 // should not continue growing. Reset the epoch when in such a period. |
| 88 epoch_ = QuicTime::Zero(); | 90 epoch_ = QuicTime::Zero(); |
| 89 } | 91 } |
| 90 | 92 |
| 93 void Cubic::SetFixConvexMode(bool fix_convex_mode) { |
| 94 fix_convex_mode_ = fix_convex_mode; |
| 95 } |
| 96 |
| 91 QuicPacketCount Cubic::CongestionWindowAfterPacketLoss( | 97 QuicPacketCount Cubic::CongestionWindowAfterPacketLoss( |
| 92 QuicPacketCount current_congestion_window) { | 98 QuicPacketCount current_congestion_window) { |
| 93 if (current_congestion_window < last_max_congestion_window_) { | 99 if (current_congestion_window < last_max_congestion_window_) { |
| 94 // We never reached the old max, so assume we are competing with another | 100 // We never reached the old max, so assume we are competing with another |
| 95 // flow. Use our extra back off factor to allow the other flow to go up. | 101 // flow. Use our extra back off factor to allow the other flow to go up. |
| 96 last_max_congestion_window_ = | 102 last_max_congestion_window_ = |
| 97 static_cast<int>(kBetaLastMax * current_congestion_window); | 103 static_cast<int>(kBetaLastMax * current_congestion_window); |
| 98 } else { | 104 } else { |
| 99 last_max_congestion_window_ = current_congestion_window; | 105 last_max_congestion_window_ = current_congestion_window; |
| 100 } | 106 } |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 132 time_to_origin_point_ = static_cast<uint32_t>( | 138 time_to_origin_point_ = static_cast<uint32_t>( |
| 133 cbrt(kCubeFactor * | 139 cbrt(kCubeFactor * |
| 134 (last_max_congestion_window_ - current_congestion_window))); | 140 (last_max_congestion_window_ - current_congestion_window))); |
| 135 origin_point_congestion_window_ = last_max_congestion_window_; | 141 origin_point_congestion_window_ = last_max_congestion_window_; |
| 136 } | 142 } |
| 137 } | 143 } |
| 138 | 144 |
| 139 // Change the time unit from microseconds to 2^10 fractions per second. Take | 145 // Change the time unit from microseconds to 2^10 fractions per second. Take |
| 140 // the round trip time in account. This is done to allow us to use shift as a | 146 // the round trip time in account. This is done to allow us to use shift as a |
| 141 // divide operator. | 147 // divide operator. |
| 142 int64_t elapsed_time = | 148 const int64_t elapsed_time = |
| 143 ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / | 149 ((current_time + delay_min - epoch_).ToMicroseconds() << 10) / |
| 144 kNumMicrosPerSecond; | 150 kNumMicrosPerSecond; |
| 151 DCHECK_GE(elapsed_time, 0); |
| 145 | 152 |
| 146 int64_t offset = time_to_origin_point_ - elapsed_time; | 153 int64_t offset = time_to_origin_point_ - elapsed_time; |
| 154 if (fix_convex_mode_) { |
| 155 // Right-shifts of negative, signed numbers have |
| 156 // implementation-dependent behavior. Force the offset to be |
| 157 // positive, similar to the kernel implementation. |
| 158 offset = labs(time_to_origin_point_ - elapsed_time); |
| 159 } |
| 160 |
| 147 QuicPacketCount delta_congestion_window = | 161 QuicPacketCount delta_congestion_window = |
| 148 (kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale; | 162 (kCubeCongestionWindowScale * offset * offset * offset) >> kCubeScale; |
| 149 | 163 |
| 164 const bool add_delta = elapsed_time > time_to_origin_point_; |
| 165 DCHECK(add_delta || |
| 166 (origin_point_congestion_window_ > delta_congestion_window)); |
| 150 QuicPacketCount target_congestion_window = | 167 QuicPacketCount target_congestion_window = |
| 151 origin_point_congestion_window_ - delta_congestion_window; | 168 (fix_convex_mode_ && add_delta) |
| 169 ? origin_point_congestion_window_ + delta_congestion_window |
| 170 : origin_point_congestion_window_ - delta_congestion_window; |
| 152 | 171 |
| 153 // Limit the CWND increase to half the acked packets rounded up to the | 172 // Limit the CWND increase to half the acked packets rounded up to the |
| 154 // nearest packet. | 173 // nearest packet. |
| 155 target_congestion_window = | 174 target_congestion_window = |
| 156 min(target_congestion_window, | 175 min(target_congestion_window, |
| 157 current_congestion_window + (epoch_packets_count_ + 1) / 2); | 176 current_congestion_window + (epoch_packets_count_ + 1) / 2); |
| 158 | 177 |
| 159 DCHECK_LT(0u, estimated_tcp_congestion_window_); | 178 DCHECK_LT(0u, estimated_tcp_congestion_window_); |
| 160 // With dynamic beta/alpha based on number of active streams, it is possible | 179 // With dynamic beta/alpha based on number of active streams, it is possible |
| 161 // for the required_ack_count to become much lower than acked_packets_count_ | 180 // for the required_ack_count to become much lower than acked_packets_count_ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 179 // congestion_window, use highest (fastest). | 198 // congestion_window, use highest (fastest). |
| 180 if (target_congestion_window < estimated_tcp_congestion_window_) { | 199 if (target_congestion_window < estimated_tcp_congestion_window_) { |
| 181 target_congestion_window = estimated_tcp_congestion_window_; | 200 target_congestion_window = estimated_tcp_congestion_window_; |
| 182 } | 201 } |
| 183 | 202 |
| 184 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; | 203 DVLOG(1) << "Final target congestion_window: " << target_congestion_window; |
| 185 return target_congestion_window; | 204 return target_congestion_window; |
| 186 } | 205 } |
| 187 | 206 |
| 188 } // namespace net | 207 } // namespace net |
| OLD | NEW |