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

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

Issue 185053006: Refactor of QUIC's rtt storage and calculation to have a single RttStats (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 9 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/tcp_cubic_sender.h" 5 #include "net/quic/congestion_control/tcp_cubic_sender.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/metrics/histogram.h" 9 #include "base/metrics/histogram.h"
10 #include "net/quic/congestion_control/rtt_stats.h"
10 11
11 using std::max; 12 using std::max;
12 using std::min; 13 using std::min;
13 14
14 namespace net { 15 namespace net {
15 16
16 namespace { 17 namespace {
17 // Constants based on TCP defaults. 18 // Constants based on TCP defaults.
18 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a 19 // The minimum cwnd based on RFC 3782 (TCP NewReno) for cwnd reductions on a
19 // fast retransmission. The cwnd after a timeout is still 1. 20 // fast retransmission. The cwnd after a timeout is still 1.
20 const QuicTcpCongestionWindow kMinimumCongestionWindow = 2; 21 const QuicTcpCongestionWindow kMinimumCongestionWindow = 2;
21 const int64 kHybridStartLowWindow = 16; 22 const int64 kHybridStartLowWindow = 16;
22 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS; 23 const QuicByteCount kMaxSegmentSize = kDefaultTCPMSS;
23 const QuicByteCount kDefaultReceiveWindow = 64000; 24 const QuicByteCount kDefaultReceiveWindow = 64000;
24 const int64 kInitialCongestionWindow = 10; 25 const int64 kInitialCongestionWindow = 10;
25 const int kMaxBurstLength = 3; 26 const int kMaxBurstLength = 3;
26 // Constants used for RTT calculation.
27 const int kInitialRttMs = 100; // At a typical RTT 100 ms.
28 const float kAlpha = 0.125f;
29 const float kOneMinusAlpha = (1 - kAlpha);
30 const float kBeta = 0.25f;
31 const float kOneMinusBeta = (1 - kBeta);
32 }; // namespace 27 }; // namespace
33 28
34 TcpCubicSender::TcpCubicSender( 29 TcpCubicSender::TcpCubicSender(
35 const QuicClock* clock, 30 const QuicClock* clock,
31 const RttStats* rtt_stats,
36 bool reno, 32 bool reno,
37 QuicTcpCongestionWindow max_tcp_congestion_window, 33 QuicTcpCongestionWindow max_tcp_congestion_window,
38 QuicConnectionStats* stats) 34 QuicConnectionStats* stats)
39 : hybrid_slow_start_(clock), 35 : hybrid_slow_start_(clock),
40 cubic_(clock, stats), 36 cubic_(clock, stats),
37 rtt_stats_(rtt_stats),
41 reno_(reno), 38 reno_(reno),
42 congestion_window_count_(0), 39 congestion_window_count_(0),
43 receive_window_(kDefaultReceiveWindow), 40 receive_window_(kDefaultReceiveWindow),
44 bytes_in_flight_(0), 41 bytes_in_flight_(0),
45 prr_out_(0), 42 prr_out_(0),
46 prr_delivered_(0), 43 prr_delivered_(0),
47 ack_count_since_loss_(0), 44 ack_count_since_loss_(0),
48 bytes_in_flight_before_loss_(0), 45 bytes_in_flight_before_loss_(0),
49 update_end_sequence_number_(true), 46 update_end_sequence_number_(true),
50 end_sequence_number_(0), 47 end_sequence_number_(0),
51 largest_sent_sequence_number_(0), 48 largest_sent_sequence_number_(0),
52 largest_acked_sequence_number_(0), 49 largest_acked_sequence_number_(0),
53 largest_sent_at_last_cutback_(0), 50 largest_sent_at_last_cutback_(0),
54 congestion_window_(kInitialCongestionWindow), 51 congestion_window_(kInitialCongestionWindow),
55 slowstart_threshold_(max_tcp_congestion_window), 52 slowstart_threshold_(max_tcp_congestion_window),
56 max_tcp_congestion_window_(max_tcp_congestion_window), 53 max_tcp_congestion_window_(max_tcp_congestion_window) {
57 delay_min_(QuicTime::Delta::Zero()),
58 smoothed_rtt_(QuicTime::Delta::Zero()),
59 mean_deviation_(QuicTime::Delta::Zero()) {
60 } 54 }
61 55
62 TcpCubicSender::~TcpCubicSender() { 56 TcpCubicSender::~TcpCubicSender() {
63 UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_); 57 UMA_HISTOGRAM_COUNTS("Net.QuicSession.FinalTcpCwnd", congestion_window_);
64 } 58 }
65 59
66 void TcpCubicSender::SetFromConfig(const QuicConfig& config, bool is_server) { 60 void TcpCubicSender::SetFromConfig(const QuicConfig& config, bool is_server) {
67 if (is_server) { 61 if (is_server) {
68 // Set the initial window size. 62 // Set the initial window size.
69 congestion_window_ = config.server_initial_congestion_window(); 63 congestion_window_ = config.server_initial_congestion_window();
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after
214 return SendWindow() - bytes_in_flight_; 208 return SendWindow() - bytes_in_flight_;
215 } 209 }
216 210
217 QuicByteCount TcpCubicSender::SendWindow() { 211 QuicByteCount TcpCubicSender::SendWindow() {
218 // What's the current send window in bytes. 212 // What's the current send window in bytes.
219 return min(receive_window_, GetCongestionWindow()); 213 return min(receive_window_, GetCongestionWindow());
220 } 214 }
221 215
222 QuicBandwidth TcpCubicSender::BandwidthEstimate() const { 216 QuicBandwidth TcpCubicSender::BandwidthEstimate() const {
223 return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(), 217 return QuicBandwidth::FromBytesAndTimeDelta(GetCongestionWindow(),
224 SmoothedRtt()); 218 rtt_stats_->SmoothedRtt());
225 }
226
227 QuicTime::Delta TcpCubicSender::SmoothedRtt() const {
228 if (smoothed_rtt_.IsZero()) {
229 return QuicTime::Delta::FromMilliseconds(kInitialRttMs);
230 }
231 return smoothed_rtt_;
232 } 219 }
233 220
234 QuicTime::Delta TcpCubicSender::RetransmissionDelay() const { 221 QuicTime::Delta TcpCubicSender::RetransmissionDelay() const {
222 if (!rtt_stats_->HasUpdates()) {
223 return QuicTime::Delta::Zero();
224 }
235 return QuicTime::Delta::FromMicroseconds( 225 return QuicTime::Delta::FromMicroseconds(
236 smoothed_rtt_.ToMicroseconds() + 4 * mean_deviation_.ToMicroseconds()); 226 rtt_stats_->SmoothedRtt().ToMicroseconds() +
227 4 * rtt_stats_->mean_deviation().ToMicroseconds());
237 } 228 }
238 229
239 QuicByteCount TcpCubicSender::GetCongestionWindow() const { 230 QuicByteCount TcpCubicSender::GetCongestionWindow() const {
240 return congestion_window_ * kMaxSegmentSize; 231 return congestion_window_ * kMaxSegmentSize;
241 } 232 }
242 233
243 bool TcpCubicSender::IsCwndLimited() const { 234 bool TcpCubicSender::IsCwndLimited() const {
244 const QuicByteCount congestion_window_bytes = congestion_window_ * 235 const QuicByteCount congestion_window_bytes = congestion_window_ *
245 kMaxSegmentSize; 236 kMaxSegmentSize;
246 if (bytes_in_flight_ >= congestion_window_bytes) { 237 if (bytes_in_flight_ >= congestion_window_bytes) {
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 ++congestion_window_count_; 284 ++congestion_window_count_;
294 if (congestion_window_count_ >= congestion_window_) { 285 if (congestion_window_count_ >= congestion_window_) {
295 ++congestion_window_; 286 ++congestion_window_;
296 congestion_window_count_ = 0; 287 congestion_window_count_ = 0;
297 } 288 }
298 289
299 DVLOG(1) << "Reno; congestion window: " << congestion_window_ 290 DVLOG(1) << "Reno; congestion window: " << congestion_window_
300 << " slowstart threshold: " << slowstart_threshold_ 291 << " slowstart threshold: " << slowstart_threshold_
301 << " congestion window count: " << congestion_window_count_; 292 << " congestion window count: " << congestion_window_count_;
302 } else { 293 } else {
303 congestion_window_ = min( 294 congestion_window_ = min(max_tcp_congestion_window_,
304 max_tcp_congestion_window_, 295 cubic_.CongestionWindowAfterAck(
305 cubic_.CongestionWindowAfterAck(congestion_window_, delay_min_)); 296 congestion_window_, rtt_stats_->min_rtt()));
306 DVLOG(1) << "Cubic; congestion window: " << congestion_window_ 297 DVLOG(1) << "Cubic; congestion window: " << congestion_window_
307 << " slowstart threshold: " << slowstart_threshold_; 298 << " slowstart threshold: " << slowstart_threshold_;
308 } 299 }
309 } 300 }
310 301
311 void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) { 302 void TcpCubicSender::OnRetransmissionTimeout(bool packets_retransmitted) {
312 bytes_in_flight_ = 0; 303 bytes_in_flight_ = 0;
313 largest_sent_at_last_cutback_ = 0; 304 largest_sent_at_last_cutback_ = 0;
314 if (packets_retransmitted) { 305 if (packets_retransmitted) {
315 cubic_.Reset(); 306 cubic_.Reset();
316 congestion_window_ = kMinimumCongestionWindow; 307 congestion_window_ = kMinimumCongestionWindow;
317 } 308 }
318 } 309 }
319 310
320 void TcpCubicSender::UpdateRtt(QuicTime::Delta rtt) { 311 void TcpCubicSender::UpdateRtt(QuicTime::Delta rtt) {
321 if (rtt.IsInfinite() || rtt.IsZero()) {
322 DVLOG(1) << "Ignoring rtt, because it's "
323 << (rtt.IsZero() ? "Zero" : "Infinite");
324 return;
325 }
326 // RTT can't be negative.
327 DCHECK_LT(0, rtt.ToMicroseconds());
328
329 // TODO(pwestin): Discard delay samples right after fast recovery,
330 // during 1 second?.
331
332 // First time call or link delay decreases.
333 if (delay_min_.IsZero() || delay_min_ > rtt) {
334 delay_min_ = rtt;
335 }
336 // First time call.
337 if (smoothed_rtt_.IsZero()) {
338 smoothed_rtt_ = rtt;
339 mean_deviation_ = QuicTime::Delta::FromMicroseconds(
340 rtt.ToMicroseconds() / 2);
341 } else {
342 mean_deviation_ = QuicTime::Delta::FromMicroseconds(
343 kOneMinusBeta * mean_deviation_.ToMicroseconds() +
344 kBeta *
345 std::abs(smoothed_rtt_.ToMicroseconds() - rtt.ToMicroseconds()));
346 smoothed_rtt_ = QuicTime::Delta::FromMicroseconds(
347 kOneMinusAlpha * smoothed_rtt_.ToMicroseconds() +
348 kAlpha * rtt.ToMicroseconds());
349 DVLOG(1) << "Cubic; smoothed_rtt_:" << smoothed_rtt_.ToMicroseconds()
350 << " mean_deviation_:" << mean_deviation_.ToMicroseconds();
351 }
352
353 // Hybrid start triggers when cwnd is larger than some threshold. 312 // Hybrid start triggers when cwnd is larger than some threshold.
354 if (congestion_window_ <= slowstart_threshold_ && 313 if (congestion_window_ <= slowstart_threshold_ &&
355 congestion_window_ >= kHybridStartLowWindow) { 314 congestion_window_ >= kHybridStartLowWindow) {
356 if (!hybrid_slow_start_.started()) { 315 if (!hybrid_slow_start_.started()) {
357 // Time to start the hybrid slow start. 316 // Time to start the hybrid slow start.
358 hybrid_slow_start_.Reset(end_sequence_number_); 317 hybrid_slow_start_.Reset(end_sequence_number_);
359 } 318 }
360 hybrid_slow_start_.Update(rtt, delay_min_); 319 hybrid_slow_start_.Update(rtt, rtt_stats_->min_rtt());
361 if (hybrid_slow_start_.Exit()) { 320 if (hybrid_slow_start_.Exit()) {
362 slowstart_threshold_ = congestion_window_; 321 slowstart_threshold_ = congestion_window_;
363 } 322 }
364 } 323 }
365 } 324 }
366 325
367 } // namespace net 326 } // namespace net
OLDNEW
« no previous file with comments | « net/quic/congestion_control/tcp_cubic_sender.h ('k') | net/quic/congestion_control/tcp_cubic_sender_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698