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 
MinOrInitialRtt()75   QuicTime::Delta MinOrInitialRtt() const {
76     return min_rtt_.IsZero() ? initial_rtt_ : min_rtt_;
77   }
78 
79   // Sets an initial RTT to be used for SmoothedRtt before any RTT updates.
set_initial_rtt(QuicTime::Delta initial_rtt)80   void set_initial_rtt(QuicTime::Delta initial_rtt) {
81     if (initial_rtt.ToMicroseconds() <= 0) {
82       QUIC_BUG << "Attempt to set initial rtt to <= 0.";
83       return;
84     }
85     initial_rtt_ = initial_rtt;
86   }
87 
88   // The most recent rtt measurement.
89   // May return Zero if no valid updates have occurred.
latest_rtt()90   QuicTime::Delta latest_rtt() const { return latest_rtt_; }
91 
92   // Returns the min_rtt for the entire connection.
93   // May return Zero if no valid updates have occurred.
min_rtt()94   QuicTime::Delta min_rtt() const { return min_rtt_; }
95 
mean_deviation()96   QuicTime::Delta mean_deviation() const { return mean_deviation_; }
97 
98   // Returns standard deviation if there is a valid one. Otherwise, returns
99   // mean_deviation_.
100   QuicTime::Delta GetStandardOrMeanDeviation() const;
101 
last_update_time()102   QuicTime last_update_time() const { return last_update_time_; }
103 
ignore_max_ack_delay()104   bool ignore_max_ack_delay() const { return ignore_max_ack_delay_; }
105 
set_ignore_max_ack_delay(bool ignore_max_ack_delay)106   void set_ignore_max_ack_delay(bool ignore_max_ack_delay) {
107     ignore_max_ack_delay_ = ignore_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   QuicTime last_update_time_;
131   // Whether to ignore the peer's max ack delay.
132   bool ignore_max_ack_delay_;
133 };
134 
135 }  // namespace quic
136 
137 #endif  // QUICHE_QUIC_CORE_CONGESTION_CONTROL_RTT_STATS_H_
138