1 // Copyright 2015 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 #ifndef NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_
6 #define NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_
13 #include "base/gtest_prod_util.h"
14 #include "base/macros.h"
15 #include "base/threading/thread_checker.h"
16 #include "base/time/time.h"
17 #include "net/base/net_export.h"
18 #include "net/base/network_change_notifier.h"
19 #include "net/base/network_quality.h"
23 // NetworkQualityEstimator provides network quality estimates (quality of the
24 // full paths to all origins that have been connected to).
25 // The estimates are based on the observed organic traffic.
26 // A NetworkQualityEstimator instance is attached to URLRequestContexts and
27 // observes the traffic of URLRequests spawned from the URLRequestContexts.
28 // A single instance of NQE can be attached to multiple URLRequestContexts,
29 // thereby increasing the single NQE instance's accuracy by providing more
30 // observed traffic characteristics.
31 class NET_EXPORT_PRIVATE NetworkQualityEstimator
32 : public NetworkChangeNotifier::ConnectionTypeObserver
{
34 // Creates a new NetworkQualityEstimator.
35 // |variation_params| is the map containing all field trial parameters
36 // related to NetworkQualityEstimator field trial.
37 explicit NetworkQualityEstimator(
38 const std::map
<std::string
, std::string
>& variation_params
);
40 ~NetworkQualityEstimator() override
;
42 // Returns the peak estimates (fastest RTT and peak throughput) of the
44 // Virtualized for testing.
45 virtual NetworkQuality
GetPeakEstimate() const;
47 // Sets |median| to the estimate of median network quality. The estimated
48 // quality is computed using a weighted median algorithm that assigns higher
49 // weight to the recent observations. |median| must not be nullptr. Returns
50 // true only if an estimate of the network quality is available (enough
51 // observations must be available to make an estimate). Virtualized for
53 virtual bool GetEstimate(NetworkQuality
* median
) const;
55 // Notifies NetworkQualityEstimator that a response has been received.
56 // |cumulative_prefilter_bytes_read| is the count of the bytes received prior
57 // to applying filters (e.g. decompression, SDCH) from request creation time
59 // |prefiltered_bytes_read| is the count of the bytes received prior
60 // to applying filters in the most recent read.
61 void NotifyDataReceived(const URLRequest
& request
,
62 int64_t cumulative_prefilter_bytes_read
,
63 int64_t prefiltered_bytes_read
);
66 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, StoreObservations
);
67 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
,
68 TestPeakKbpsFastestRTTUpdates
);
69 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, TestAddObservation
);
70 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, ObtainOperatingParams
);
71 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, HalfLifeParam
);
72 FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP
, NetworkQualityEstimator
);
73 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
,
74 PercentileSameTimestamps
);
75 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
,
76 PercentileDifferentTimestamps
);
77 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, ComputedPercentiles
);
79 // Records the round trip time or throughput observation, along with the time
80 // the observation was made.
81 struct NET_EXPORT_PRIVATE Observation
{
82 Observation(int32_t value
, base::TimeTicks timestamp
);
86 // Value of the observation.
89 // Time when the observation was taken.
90 const base::TimeTicks timestamp
;
93 // Holds an observation and its weight.
94 struct WeightedObservation
{
95 WeightedObservation(int32_t value
, double weight
)
96 : value(value
), weight(weight
) {}
97 WeightedObservation(const WeightedObservation
& other
)
98 : WeightedObservation(other
.value
, other
.weight
) {}
100 WeightedObservation
& operator=(const WeightedObservation
& other
) {
102 weight
= other
.weight
;
106 // Required for sorting the samples in the ascending order of values.
107 bool operator<(const WeightedObservation
& other
) const {
108 return (value
< other
.value
);
111 // Value of the sample.
114 // Weight of the sample. This is computed based on how much time has passed
115 // since the sample was taken.
119 // Stores observations sorted by time.
120 class NET_EXPORT_PRIVATE ObservationBuffer
{
122 explicit ObservationBuffer(double weight_multiplier_per_second
);
124 ~ObservationBuffer();
126 // Adds |observation| to the buffer. The oldest observation in the buffer
127 // will be evicted to make room if the buffer is already full.
128 void AddObservation(const Observation
& observation
);
130 // Returns the number of observations in this buffer.
133 // Clears the observations stored in this buffer.
136 // Returns the |percentile| value of the observations in this buffer.
137 int32_t GetPercentile(int percentile
) const;
140 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, StoreObservations
);
141 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
,
142 ObtainOperatingParams
);
143 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest
, HalfLifeParam
);
145 // Computes the weighted observations and stores them in
146 // |weighted_observations| sorted by ascending |WeightedObservation.value|.
147 // Sets |total_weight| to the total weight of all observations. Should be
148 // called only when there is at least one observation in the buffer.
149 void ComputeWeightedObservations(
150 std::vector
<WeightedObservation
>& weighted_observations
,
151 double* total_weight
) const;
153 // Holds observations sorted by time, with the oldest observation at the
154 // front of the queue.
155 std::deque
<Observation
> observations_
;
157 // The factor by which the weight of an observation reduces every second.
158 // For example, if an observation is 6 seconds old, its weight would be:
159 // weight_multiplier_per_second_ ^ 6
160 // Calculated from |kHalfLifeSeconds| by solving the following equation:
161 // weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5
162 const double weight_multiplier_per_second_
;
164 DISALLOW_COPY_AND_ASSIGN(ObservationBuffer
);
167 // Tiny transfer sizes may give inaccurate throughput results.
168 // Minimum size of the transfer over which the throughput is computed.
169 static const int kMinTransferSizeInBytes
= 10000;
171 // Minimum duration (in microseconds) of the transfer over which the
172 // throughput is computed.
173 static const int kMinRequestDurationMicroseconds
= 1000;
175 // Minimum valid value of the variation parameter that holds RTT (in
176 // milliseconds) values.
177 static const int kMinimumRTTVariationParameterMsec
= 1;
179 // Minimum valid value of the variation parameter that holds throughput (in
181 static const int kMinimumThroughputVariationParameterKbps
= 1;
183 // Construct a NetworkQualityEstimator instance allowing for test
184 // configuration. Registers for network type change notifications so estimates
185 // can be kept network specific.
186 // |variation_params| is the map containing all field trial parameters for the
187 // network quality estimator field trial.
188 // |allow_local_host_requests_for_tests| should only be true when testing
189 // against local HTTP server and allows the requests to local host to be
190 // used for network quality estimation.
191 // |allow_smaller_responses_for_tests| should only be true when testing
192 // against local HTTP server and allows the responses smaller than
193 // |kMinTransferSizeInBytes| or shorter than |kMinRequestDurationMicroseconds|
194 // to be used for network quality estimation.
195 NetworkQualityEstimator(
196 const std::map
<std::string
, std::string
>& variation_params
,
197 bool allow_local_host_requests_for_tests
,
198 bool allow_smaller_responses_for_tests
);
200 // Obtains operating parameters from the field trial parameters.
201 void ObtainOperatingParams(
202 const std::map
<std::string
, std::string
>& variation_params
);
204 // Adds the default median RTT and downstream throughput estimate for the
205 // current connection type to the observation buffer.
206 void AddDefaultEstimates();
208 // Returns the maximum size of the observation buffer.
210 size_t GetMaximumObservationBufferSizeForTests() const;
212 // Returns true if the size of all observation buffers is equal to the
213 // |expected_size|. Used for testing.
214 bool VerifyBufferSizeForTests(size_t expected_size
) const;
216 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
217 void OnConnectionTypeChanged(
218 NetworkChangeNotifier::ConnectionType type
) override
;
220 // Returns an estimate of network quality at the specified |percentile|.
221 // |percentile| must be between 0 and 100 (both inclusive) with higher
222 // percentiles indicating less performant networks. For example, if
223 // |percentile| is 90, then the network is expected to be faster than the
224 // returned estimate with 0.9 probability. Similarly, network is expected to
225 // be slower than the returned estimate with 0.1 probability.
226 NetworkQuality
GetEstimate(int percentile
) const;
228 // Determines if the requests to local host can be used in estimating the
229 // network quality. Set to true only for tests.
230 const bool allow_localhost_requests_
;
232 // Determines if the responses smaller than |kMinTransferSizeInBytes|
233 // or shorter than |kMinTransferSizeInBytes| can be used in estimating the
234 // network quality. Set to true only for tests.
235 const bool allow_small_responses_
;
237 // Time when last connection change was observed.
238 base::TimeTicks last_connection_change_
;
240 // Last value passed to |OnConnectionTypeChanged|. This indicates the
241 // current connection type.
242 NetworkChangeNotifier::ConnectionType current_connection_type_
;
244 // Fastest round-trip-time (RTT) since last connectivity change. RTT measured
245 // from URLRequest creation until first byte received.
246 base::TimeDelta fastest_rtt_since_last_connection_change_
;
248 // Rough measurement of downstream peak Kbps witnessed since last connectivity
249 // change. The accuracy is decreased by ignoring these factors:
250 // 1) Multiple URLRequests can occur concurrently.
251 // 2) The transfer time includes at least one RTT while no bytes are read.
252 int32_t peak_kbps_since_last_connection_change_
;
254 // Buffer that holds Kbps observations sorted by timestamp.
255 ObservationBuffer kbps_observations_
;
257 // Buffer that holds RTT (in milliseconds) observations sorted by timestamp.
258 ObservationBuffer rtt_msec_observations_
;
260 // Default network quality observations obtained from the network quality
261 // estimator field trial parameters. The observations are indexed by
264 default_observations_
[NetworkChangeNotifier::CONNECTION_LAST
+ 1];
266 base::ThreadChecker thread_checker_
;
268 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator
);
273 #endif // NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_