1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "net/quic/congestion_control/rtt_stats.h"
11 // Default initial rtt used before any samples are received.
12 const int kInitialRttMs = 100;
13 const float kAlpha = 0.125f;
14 const float kOneMinusAlpha = (1 - kAlpha);
15 const float kBeta = 0.25f;
16 const float kOneMinusBeta = (1 - kBeta);
17 const float kHalfWindow = 0.5f;
18 const float kQuarterWindow = 0.25f;
23 : latest_rtt_(QuicTime::Delta::Zero()),
24 min_rtt_(QuicTime::Delta::Zero()),
25 smoothed_rtt_(QuicTime::Delta::Zero()),
26 mean_deviation_(QuicTime::Delta::Zero()),
27 initial_rtt_us_(kInitialRttMs * base::Time::kMicrosecondsPerMillisecond),
28 num_min_rtt_samples_remaining_(0),
29 recent_min_rtt_window_(QuicTime::Delta::Zero()) { }
31 bool RttStats::HasUpdates() const {
32 return !smoothed_rtt_.IsZero();
35 void RttStats::SampleNewRecentMinRtt(uint32 num_samples) {
36 num_min_rtt_samples_remaining_ = num_samples;
37 new_min_rtt_ = RttSample();
40 // Updates the RTT based on a new sample.
41 void RttStats::UpdateRtt(QuicTime::Delta send_delta,
42 QuicTime::Delta ack_delay,
44 QuicTime::Delta rtt_sample(QuicTime::Delta::Zero());
45 if (send_delta > ack_delay) {
46 rtt_sample = send_delta.Subtract(ack_delay);
47 } else if (!HasUpdates()) {
48 // Even though we received information from the peer suggesting
49 // an invalid (negative) RTT, we can use the send delta as an
50 // approximation until we get a better estimate.
51 rtt_sample = send_delta;
54 if (rtt_sample.IsInfinite() || rtt_sample.IsZero()) {
55 DVLOG(1) << "Ignoring rtt, because it's "
56 << (rtt_sample.IsZero() ? "Zero" : "Infinite");
59 // RTT can't be negative.
60 DCHECK_LT(0, rtt_sample.ToMicroseconds());
62 latest_rtt_ = rtt_sample;
63 // First time call or link delay decreases.
64 if (min_rtt_.IsZero() || min_rtt_ > rtt_sample) {
65 min_rtt_ = rtt_sample;
67 UpdateRecentMinRtt(rtt_sample, now);
70 smoothed_rtt_ = rtt_sample;
71 mean_deviation_ = QuicTime::Delta::FromMicroseconds(
72 rtt_sample.ToMicroseconds() / 2);
74 mean_deviation_ = QuicTime::Delta::FromMicroseconds(
75 kOneMinusBeta * mean_deviation_.ToMicroseconds() +
76 kBeta * std::abs(smoothed_rtt_.Subtract(rtt_sample).ToMicroseconds()));
77 smoothed_rtt_ = smoothed_rtt_.Multiply(kOneMinusAlpha).Add(
78 rtt_sample.Multiply(kAlpha));
79 DVLOG(1) << "Cubic; smoothed_rtt(us):" << smoothed_rtt_.ToMicroseconds()
80 << " mean_deviation(us):" << mean_deviation_.ToMicroseconds();
84 void RttStats::UpdateRecentMinRtt(QuicTime::Delta rtt_sample, QuicTime now) {
85 // Recent min_rtt update.
86 if (num_min_rtt_samples_remaining_ > 0) {
87 --num_min_rtt_samples_remaining_;
88 if (new_min_rtt_.rtt.IsZero() || rtt_sample <= new_min_rtt_.rtt) {
89 new_min_rtt_ = RttSample(rtt_sample, now);
91 if (num_min_rtt_samples_remaining_ == 0) {
92 quarter_window_rtt_ = half_window_rtt_ = recent_min_rtt_ = new_min_rtt_;
96 // Update the three recent rtt samples.
97 if (recent_min_rtt_.rtt.IsZero() || rtt_sample <= recent_min_rtt_.rtt) {
98 recent_min_rtt_ = RttSample(rtt_sample, now);
99 quarter_window_rtt_ = half_window_rtt_ = recent_min_rtt_;
100 } else if (rtt_sample <= half_window_rtt_.rtt) {
101 half_window_rtt_ = RttSample(rtt_sample, now);
102 quarter_window_rtt_ = half_window_rtt_;
103 } else if (rtt_sample <= quarter_window_rtt_.rtt) {
104 quarter_window_rtt_ = RttSample(rtt_sample, now);
107 // Expire old min rtt samples.
108 if (recent_min_rtt_.time < now.Subtract(recent_min_rtt_window_)) {
109 recent_min_rtt_ = half_window_rtt_;
110 half_window_rtt_ = quarter_window_rtt_;
111 quarter_window_rtt_ = RttSample(rtt_sample, now);
112 } else if (half_window_rtt_.time <
113 now.Subtract(recent_min_rtt_window_.Multiply(kHalfWindow))) {
114 half_window_rtt_ = quarter_window_rtt_;
115 quarter_window_rtt_ = RttSample(rtt_sample, now);
116 } else if (quarter_window_rtt_.time <
117 now.Subtract(recent_min_rtt_window_.Multiply(kQuarterWindow))) {
118 quarter_window_rtt_ = RttSample(rtt_sample, now);
122 QuicTime::Delta RttStats::SmoothedRtt() const {
124 return QuicTime::Delta::FromMicroseconds(initial_rtt_us_);
126 return smoothed_rtt_;