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.
4 
5 // A convenience class to store rtt samples and calculate smoothed rtt.
6 
7 #ifndef QUICHE_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
8 #define QUICHE_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
9 
10 #include <algorithm>
11 #include <cstdint>
12 
13 #include "net/third_party/quiche/src/quic/core/quic_packets.h"
14 #include "net/third_party/quiche/src/quic/core/quic_time.h"
15 #include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
16 #include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
17 
18 namespace quic {
19 
20 namespace test {
21 class RttStatsPeer;
22 }  // namespace test
23 
24 class QUIC_EXPORT_PRIVATE RttStats {
25  public:
26   // Calculates running standard-deviation using Welford's algorithm:
27   // https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#
28   // Welford's_Online_algorithm.
29   struct QUIC_EXPORT_PRIVATE StandardDeviationCaculator {
StandardDeviationCaculatorStandardDeviationCaculator30     StandardDeviationCaculator() {}
31 
32     // Called when a new RTT sample is available.
33     void OnNewRttSample(QuicTime::Delta rtt_sample,
34                         QuicTime::Delta smoothed_rtt);
35     // Calculates the standard deviation.
36     QuicTime::Delta CalculateStandardDeviation() const;
37 
38     bool has_valid_standard_deviation = false;
39 
40    private:
41     double m2 = 0;
42   };
43 
44   RttStats();
45   RttStats(const RttStats&) = delete;
46   RttStats& operator=(const RttStats&) = delete;
47 
48   // Updates the RTT from an incoming ack which is received |send_delta| after
49   // the packet is sent and the peer reports the ack being delayed |ack_delay|.
50   void UpdateRtt(QuicTime::Delta send_delta,
51                  QuicTime::Delta ack_delay,
52                  QuicTime now);
53 
54   // Causes the smoothed_rtt to be increased to the latest_rtt if the latest_rtt
55   // is larger. The mean deviation is increased to the most recent deviation if
56   // it's larger.
57   void ExpireSmoothedMetrics();
58 
59   // Called when connection migrates and rtt measurement needs to be reset.
60   void OnConnectionMigration();
61 
62   // Returns the EWMA smoothed RTT for the connection.
63   // May return Zero if no valid updates have occurred.
smoothed_rtt()64   QuicTime::Delta smoothed_rtt() const { return smoothed_rtt_; }
65 
66   // Returns the EWMA smoothed RTT prior to the most recent RTT sample.
previous_srtt()67   QuicTime::Delta previous_srtt() const { return previous_srtt_; }
68 
initial_rtt()69   QuicTime::Delta initial_rtt() const { return initial_rtt_; }
70 
SmoothedOrInitialRtt()71   QuicTime::Delta SmoothedOrInitialRtt() const {
72     return smoothed_rtt_.IsZero() ? initial_rtt_ : smoothed_rtt_;
73   }
74 
75   // Sets an initial RTT to be used for SmoothedRtt before any RTT updates.
set_initial_rtt(QuicTime::Delta initial_rtt)76   void set_initial_rtt(QuicTime::Delta initial_rtt) {
77     if (initial_rtt.ToMicroseconds() <= 0) {
78       QUIC_BUG << "Attempt to set initial rtt to <= 0.";
79       return;
80     }
81     initial_rtt_ = initial_rtt;
82   }
83 
84   // The most recent rtt measurement.
85   // May return Zero if no valid updates have occurred.
latest_rtt()86   QuicTime::Delta latest_rtt() const { return latest_rtt_; }
87 
88   // Returns the min_rtt for the entire connection.
89   // May return Zero if no valid updates have occurred.
min_rtt()90   QuicTime::Delta min_rtt() const { return min_rtt_; }
91 
mean_deviation()92   QuicTime::Delta mean_deviation() const { return mean_deviation_; }
93 
94   // Returns standard deviation if there is a valid one. Otherwise, returns
95   // mean_deviation_.
96   QuicTime::Delta GetStandardOrMeanDeviation() const;
97 
last_update_time()98   QuicTime last_update_time() const { return last_update_time_; }
99 
ignore_max_ack_delay()100   bool ignore_max_ack_delay() const { return ignore_max_ack_delay_; }
101 
set_ignore_max_ack_delay(bool ignore_max_ack_delay)102   void set_ignore_max_ack_delay(bool ignore_max_ack_delay) {
103     ignore_max_ack_delay_ = ignore_max_ack_delay;
104   }
105 
set_initial_max_ack_delay(QuicTime::Delta initial_max_ack_delay)106   void set_initial_max_ack_delay(QuicTime::Delta initial_max_ack_delay) {
107     max_ack_delay_ = std::max(max_ack_delay_, initial_max_ack_delay);
108   }
109 
EnableStandardDeviationCalculation()110   void EnableStandardDeviationCalculation() {
111     calculate_standard_deviation_ = true;
112   }
113 
114  private:
115   friend class test::RttStatsPeer;
116 
117   QuicTime::Delta latest_rtt_;
118   QuicTime::Delta min_rtt_;
119   QuicTime::Delta smoothed_rtt_;
120   QuicTime::Delta previous_srtt_;
121   // Mean RTT deviation during this session.
122   // Approximation of standard deviation, the error is roughly 1.25 times
123   // larger than the standard deviation, for a normally distributed signal.
124   QuicTime::Delta mean_deviation_;
125   // Standard deviation calculator. Only used calculate_standard_deviation_ is
126   // true.
127   StandardDeviationCaculator standard_deviation_calculator_;
128   bool calculate_standard_deviation_;
129   QuicTime::Delta initial_rtt_;
130   // The maximum ack delay observed over the connection after excluding ack
131   // delays that were too large to be included in an RTT measurement.
132   // TODO(ianswett): Remove when deprecating quic_sent_packet_manager_cleanup.
133   QuicTime::Delta max_ack_delay_;
134   QuicTime last_update_time_;
135   // Whether to ignore the peer's max ack delay.
136   bool ignore_max_ack_delay_;
137 };
138 
139 }  // namespace quic
140 
141 #endif  // QUICHE_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
142