Mac Partial Swap: Fix sub-layer rounding issue
[chromium-blink-merge.git] / net / base / network_quality_estimator.h
blobdb2976bd0ab681c986563063b908f5d398aa3566
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_
8 #include <stdint.h>
10 #include <deque>
11 #include <map>
12 #include <string>
14 #include "base/gtest_prod_util.h"
15 #include "base/macros.h"
16 #include "base/memory/scoped_ptr.h"
17 #include "base/threading/thread_checker.h"
18 #include "base/time/time.h"
19 #include "net/base/net_export.h"
20 #include "net/base/network_change_notifier.h"
22 namespace net {
24 class URLRequest;
26 // NetworkQualityEstimator provides network quality estimates (quality of the
27 // full paths to all origins that have been connected to).
28 // The estimates are based on the observed organic traffic.
29 // A NetworkQualityEstimator instance is attached to URLRequestContexts and
30 // observes the traffic of URLRequests spawned from the URLRequestContexts.
31 // A single instance of NQE can be attached to multiple URLRequestContexts,
32 // thereby increasing the single NQE instance's accuracy by providing more
33 // observed traffic characteristics.
34 class NET_EXPORT_PRIVATE NetworkQualityEstimator
35 : public NetworkChangeNotifier::ConnectionTypeObserver {
36 public:
37 // Creates a new NetworkQualityEstimator.
38 // |variation_params| is the map containing all field trial parameters
39 // related to NetworkQualityEstimator field trial.
40 explicit NetworkQualityEstimator(
41 const std::map<std::string, std::string>& variation_params);
43 ~NetworkQualityEstimator() override;
45 // Returns true if RTT is available and sets |rtt| to estimated RTT.
46 // Virtualized for testing.
47 virtual bool GetRTTEstimate(base::TimeDelta* rtt) const;
49 // Returns true if downlink throughput is available and sets |kbps| to
50 // estimated downlink throughput (in Kilobits per second).
51 // Virtualized for testing.
52 virtual bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const;
54 // Notifies NetworkQualityEstimator that the response header of |request| has
55 // been received.
56 void NotifyHeadersReceived(const URLRequest& request);
58 // Notifies NetworkQualityEstimator that the response body of |request| has
59 // been received.
60 void NotifyRequestCompleted(const URLRequest& request);
62 // Returns true if median RTT is available and sets |rtt| to the median of
63 // RTT observations since |begin_timestamp|.
64 bool GetMedianRTTSince(const base::TimeTicks& begin_timestamp,
65 base::TimeDelta* rtt) const;
67 protected:
68 // NetworkID is used to uniquely identify a network.
69 // For the purpose of network quality estimation and caching, a network is
70 // uniquely identified by a combination of |type| and
71 // |id|. This approach is unable to distinguish networks with
72 // same name (e.g., different Wi-Fi networks with same SSID).
73 // This is a protected member to expose it to tests.
74 struct NET_EXPORT_PRIVATE NetworkID {
75 NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id)
76 : type(type), id(id) {}
77 NetworkID(const NetworkID& other) : type(other.type), id(other.id) {}
78 ~NetworkID() {}
80 NetworkID& operator=(const NetworkID& other) {
81 type = other.type;
82 id = other.id;
83 return *this;
86 // Overloaded because NetworkID is used as key in a map.
87 bool operator<(const NetworkID& other) const {
88 return type < other.type || (type == other.type && id < other.id);
91 // Connection type of the network.
92 NetworkChangeNotifier::ConnectionType type;
94 // Name of this network. This is set to:
95 // - Wi-Fi SSID if the device is connected to a Wi-Fi access point and the
96 // SSID name is available, or
97 // - MCC/MNC code of the cellular carrier if the device is connected to a
98 // cellular network, or
99 // - "Ethernet" in case the device is connected to ethernet.
100 // - An empty string in all other cases or if the network name is not
101 // exposed by platform APIs.
102 std::string id;
105 // Construct a NetworkQualityEstimator instance allowing for test
106 // configuration. Registers for network type change notifications so estimates
107 // can be kept network specific.
108 // |variation_params| is the map containing all field trial parameters for the
109 // network quality estimator field trial.
110 // |allow_local_host_requests_for_tests| should only be true when testing
111 // against local HTTP server and allows the requests to local host to be
112 // used for network quality estimation.
113 // |allow_smaller_responses_for_tests| should only be true when testing.
114 // Allows the responses smaller than |kMinTransferSizeInBytes| or shorter than
115 // |kMinRequestDurationMicroseconds| to be used for network quality
116 // estimation.
117 NetworkQualityEstimator(
118 const std::map<std::string, std::string>& variation_params,
119 bool allow_local_host_requests_for_tests,
120 bool allow_smaller_responses_for_tests);
122 // Returns true if the cached network quality estimate was successfully read.
123 bool ReadCachedNetworkQualityEstimate();
125 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
126 void OnConnectionTypeChanged(
127 NetworkChangeNotifier::ConnectionType type) override;
129 private:
130 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
131 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestKbpsRTTUpdates);
132 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation);
133 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams);
134 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
135 FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, NetworkQualityEstimator);
136 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
137 PercentileSameTimestamps);
138 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
139 PercentileDifferentTimestamps);
140 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles);
141 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestCaching);
142 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
143 TestLRUCacheMaximumSize);
144 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMedianRTTSince);
146 // NetworkQuality is used to cache the quality of a network connection.
147 class NET_EXPORT_PRIVATE NetworkQuality {
148 public:
149 NetworkQuality();
150 // |rtt| is the estimate of the round trip time.
151 // |downstream_throughput_kbps| is the estimate of the downstream
152 // throughput.
153 NetworkQuality(const base::TimeDelta& rtt,
154 int32_t downstream_throughput_kbps);
155 NetworkQuality(const NetworkQuality& other);
156 ~NetworkQuality();
158 NetworkQuality& operator=(const NetworkQuality& other);
160 // Returns the estimate of the round trip time.
161 const base::TimeDelta& rtt() const { return rtt_; }
163 // Returns the estimate of the downstream throughput in Kbps (Kilo bits per
164 // second).
165 int32_t downstream_throughput_kbps() const {
166 return downstream_throughput_kbps_;
169 private:
170 // Estimated round trip time.
171 base::TimeDelta rtt_;
173 // Estimated downstream throughput in Kbps.
174 int32_t downstream_throughput_kbps_;
177 // CachedNetworkQuality stores the quality of a previously seen network.
178 class NET_EXPORT_PRIVATE CachedNetworkQuality {
179 public:
180 explicit CachedNetworkQuality(const NetworkQuality& network_quality);
181 CachedNetworkQuality(const CachedNetworkQuality& other);
182 ~CachedNetworkQuality();
184 // Returns the network quality associated with this cached entry.
185 const NetworkQuality network_quality() const { return network_quality_; }
187 // Returns true if this cache entry was updated before
188 // |cached_network_quality|.
189 bool OlderThan(const CachedNetworkQuality& cached_network_quality) const;
191 // Time when this cache entry was last updated.
192 const base::TimeTicks last_update_time_;
194 // Quality of this cached network.
195 const NetworkQuality network_quality_;
197 private:
198 DISALLOW_ASSIGN(CachedNetworkQuality);
201 // Records the round trip time or throughput observation, along with the time
202 // the observation was made.
203 struct NET_EXPORT_PRIVATE Observation {
204 Observation(int32_t value, base::TimeTicks timestamp);
205 ~Observation();
207 // Value of the observation.
208 const int32_t value;
210 // Time when the observation was taken.
211 const base::TimeTicks timestamp;
214 // Holds an observation and its weight.
215 struct NET_EXPORT_PRIVATE WeightedObservation {
216 WeightedObservation(int32_t value, double weight)
217 : value(value), weight(weight) {}
218 WeightedObservation(const WeightedObservation& other)
219 : WeightedObservation(other.value, other.weight) {}
221 WeightedObservation& operator=(const WeightedObservation& other) {
222 value = other.value;
223 weight = other.weight;
224 return *this;
227 // Required for sorting the samples in the ascending order of values.
228 bool operator<(const WeightedObservation& other) const {
229 return (value < other.value);
232 // Value of the sample.
233 int32_t value;
235 // Weight of the sample. This is computed based on how much time has passed
236 // since the sample was taken.
237 double weight;
240 // Stores observations sorted by time.
241 class NET_EXPORT_PRIVATE ObservationBuffer {
242 public:
243 explicit ObservationBuffer(double weight_multiplier_per_second);
244 ~ObservationBuffer();
246 // Adds |observation| to the buffer. The oldest observation in the buffer
247 // will be evicted to make room if the buffer is already full.
248 void AddObservation(const Observation& observation);
250 // Returns the number of observations in this buffer.
251 size_t Size() const;
253 // Clears the observations stored in this buffer.
254 void Clear();
256 // Returns true iff the |percentile| value of the observations in this
257 // buffer is available. Sets |result| to the computed |percentile|
258 // value among all observations since |begin_timestamp|. If the value is
259 // unavailable, false is returned and |result| is not modified. Percentile
260 // value is unavailable if all the values in observation buffer are older
261 // than |begin_timestamp|.
262 // |result| must not be null.
263 bool GetPercentile(const base::TimeTicks& begin_timestamp,
264 int32_t* result,
265 int percentile) const;
267 private:
268 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
269 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
270 ObtainOperatingParams);
271 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
273 // Computes the weighted observations and stores them in
274 // |weighted_observations| sorted by ascending |WeightedObservation.value|.
275 // Only the observations with timestamp later than |begin_timestamp| are
276 // considered. Also, sets |total_weight| to the total weight of all
277 // observations. Should be called only when there is at least one
278 // observation in the buffer.
279 void ComputeWeightedObservations(
280 const base::TimeTicks& begin_timestamp,
281 std::vector<WeightedObservation>& weighted_observations,
282 double* total_weight) const;
284 // Holds observations sorted by time, with the oldest observation at the
285 // front of the queue.
286 std::deque<Observation> observations_;
288 // The factor by which the weight of an observation reduces every second.
289 // For example, if an observation is 6 seconds old, its weight would be:
290 // weight_multiplier_per_second_ ^ 6
291 // Calculated from |kHalfLifeSeconds| by solving the following equation:
292 // weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5
293 const double weight_multiplier_per_second_;
295 DISALLOW_COPY_AND_ASSIGN(ObservationBuffer);
298 // This does not use a unordered_map or hash_map for code simplicity (key just
299 // implements operator<, rather than hash and equality) and because the map is
300 // tiny.
301 typedef std::map<NetworkID, CachedNetworkQuality> CachedNetworkQualities;
303 // Throughput is set to |kInvalidThroughput| if a valid value is
304 // unavailable. Readers should discard throughput value if it is set to
305 // |kInvalidThroughput|.
306 static const int32_t kInvalidThroughput;
308 // Tiny transfer sizes may give inaccurate throughput results.
309 // Minimum size of the transfer over which the throughput is computed.
310 static const int kMinTransferSizeInBytes = 10000;
312 // Minimum duration (in microseconds) of the transfer over which the
313 // throughput is computed.
314 static const int kMinRequestDurationMicroseconds = 1000;
316 // Minimum valid value of the variation parameter that holds RTT (in
317 // milliseconds) values.
318 static const int kMinimumRTTVariationParameterMsec = 1;
320 // Minimum valid value of the variation parameter that holds throughput (in
321 // kbps) values.
322 static const int kMinimumThroughputVariationParameterKbps = 1;
324 // Maximum size of the cache that holds network quality estimates.
325 // Smaller size may reduce the cache hit rate due to frequent evictions.
326 // Larger size may affect performance.
327 static const size_t kMaximumNetworkQualityCacheSize = 10;
329 // Maximum number of observations that can be held in the ObservationBuffer.
330 static const size_t kMaximumObservationsBufferSize = 300;
332 // Returns the RTT value to be used when the valid RTT is unavailable. Readers
333 // should discard RTT if it is set to the value returned by |InvalidRTT()|.
334 static const base::TimeDelta InvalidRTT();
336 // Obtains operating parameters from the field trial parameters.
337 void ObtainOperatingParams(
338 const std::map<std::string, std::string>& variation_params);
340 // Adds the default median RTT and downstream throughput estimate for the
341 // current connection type to the observation buffer.
342 void AddDefaultEstimates();
344 // Returns an estimate of network quality at the specified |percentile|.
345 // Only the observations later than |begin_timestamp| are taken into account.
346 // |percentile| must be between 0 and 100 (both inclusive) with higher
347 // percentiles indicating less performant networks. For example, if
348 // |percentile| is 90, then the network is expected to be faster than the
349 // returned estimate with 0.9 probability. Similarly, network is expected to
350 // be slower than the returned estimate with 0.1 probability.
351 base::TimeDelta GetRTTEstimateInternal(const base::TimeTicks& begin_timestamp,
352 int percentile) const;
353 int32_t GetDownlinkThroughputKbpsEstimateInternal(
354 const base::TimeTicks& begin_timestamp,
355 int percentile) const;
357 // Returns the current network ID checking by calling the platform APIs.
358 // Virtualized for testing.
359 virtual NetworkID GetCurrentNetworkID() const;
361 // Writes the estimated quality of the current network to the cache.
362 void CacheNetworkQualityEstimate();
364 // Records the UMA related to RTT.
365 void RecordRTTUMA(int32_t estimated_value_msec,
366 int32_t actual_value_msec) const;
368 // Returns true only if |request| can be used for network quality estimation.
369 // Only the requests that go over network are considered to provide useful
370 // observations.
371 bool RequestProvidesUsefulObservations(const URLRequest& request) const;
373 // Determines if the requests to local host can be used in estimating the
374 // network quality. Set to true only for tests.
375 const bool allow_localhost_requests_;
377 // Determines if the responses smaller than |kMinTransferSizeInBytes|
378 // or shorter than |kMinTransferSizeInBytes| can be used in estimating the
379 // network quality. Set to true only for tests.
380 const bool allow_small_responses_;
382 // Time when last connection change was observed.
383 base::TimeTicks last_connection_change_;
385 // ID of the current network.
386 NetworkID current_network_id_;
388 // Peak network quality (fastest round-trip-time (RTT) and highest
389 // downstream throughput) measured since last connectivity change. RTT is
390 // measured from time the request is sent until the first byte received.
391 // The accuracy is decreased by ignoring these factors:
392 // 1) Multiple URLRequests can occur concurrently.
393 // 2) Includes server processing time.
394 NetworkQuality peak_network_quality_;
396 // Cache that stores quality of previously seen networks.
397 CachedNetworkQualities cached_network_qualities_;
399 // Buffer that holds Kbps observations sorted by timestamp.
400 ObservationBuffer downstream_throughput_kbps_observations_;
402 // Buffer that holds RTT (in milliseconds) observations sorted by timestamp.
403 ObservationBuffer rtt_msec_observations_;
405 // Default network quality observations obtained from the network quality
406 // estimator field trial parameters. The observations are indexed by
407 // ConnectionType.
408 NetworkQuality
409 default_observations_[NetworkChangeNotifier::CONNECTION_LAST + 1];
411 // Estimated network quality. Updated on mainframe requests.
412 NetworkQuality estimated_median_network_quality_;
414 base::ThreadChecker thread_checker_;
416 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator);
419 } // namespace net
421 #endif // NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_