Cleanup setting of 'sysroot' in common.gypi
[chromium-blink-merge.git] / net / base / network_quality_estimator.h
blobf951bd4f7fa533b72dd88a7ec01243c31cf6d38f
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/external_estimate_provider.h"
20 #include "net/base/net_export.h"
21 #include "net/base/network_change_notifier.h"
22 #include "net/base/socket_performance_watcher.h"
23 #include "net/base/socket_performance_watcher_factory.h"
25 namespace net {
27 class URLRequest;
29 // NetworkQualityEstimator provides network quality estimates (quality of the
30 // full paths to all origins that have been connected to).
31 // The estimates are based on the observed organic traffic.
32 // A NetworkQualityEstimator instance is attached to URLRequestContexts and
33 // observes the traffic of URLRequests spawned from the URLRequestContexts.
34 // A single instance of NQE can be attached to multiple URLRequestContexts,
35 // thereby increasing the single NQE instance's accuracy by providing more
36 // observed traffic characteristics.
37 class NET_EXPORT_PRIVATE NetworkQualityEstimator
38 : public NetworkChangeNotifier::ConnectionTypeObserver,
39 public ExternalEstimateProvider::UpdatedEstimateDelegate,
40 public SocketPerformanceWatcherFactory {
41 public:
42 // Creates a new NetworkQualityEstimator.
43 // |variation_params| is the map containing all field trial parameters
44 // related to NetworkQualityEstimator field trial.
45 // |external_estimates_provider| may be NULL.
46 NetworkQualityEstimator(
47 scoped_ptr<ExternalEstimateProvider> external_estimates_provider,
48 const std::map<std::string, std::string>& variation_params);
50 ~NetworkQualityEstimator() override;
52 // Returns true if RTT is available and sets |rtt| to estimated RTT.
53 // Virtualized for testing. |rtt| should not be null.
54 virtual bool GetRTTEstimate(base::TimeDelta* rtt) const;
56 // Returns true if downlink throughput is available and sets |kbps| to
57 // estimated downlink throughput (in Kilobits per second).
58 // Virtualized for testing. |kbps| should not be null.
59 virtual bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const;
61 // Notifies NetworkQualityEstimator that the response header of |request| has
62 // been received.
63 void NotifyHeadersReceived(const URLRequest& request);
65 // Notifies NetworkQualityEstimator that the response body of |request| has
66 // been received.
67 void NotifyRequestCompleted(const URLRequest& request);
69 // Returns true if median RTT is available and sets |rtt| to the median of
70 // RTT observations since |begin_timestamp|.
71 // Virtualized for testing. |rtt| should not be null.
72 virtual bool GetRecentMedianRTT(const base::TimeTicks& begin_timestamp,
73 base::TimeDelta* rtt) const;
75 // Returns true if median downstream throughput is available and sets |kbps|
76 // to the median of downstream Kbps observations since |begin_timestamp|.
77 // Virtualized for testing. |kbps| should not be null.
78 virtual bool GetRecentMedianDownlinkThroughputKbps(
79 const base::TimeTicks& begin_timestamp,
80 int32_t* kbps) const;
82 // SocketPerformanceWatcherFactory implementation:
83 scoped_ptr<SocketPerformanceWatcher> CreateTCPSocketPerformanceWatcher()
84 const override;
85 scoped_ptr<SocketPerformanceWatcher> CreateUDPSocketPerformanceWatcher()
86 const override;
88 protected:
89 // NetworkID is used to uniquely identify a network.
90 // For the purpose of network quality estimation and caching, a network is
91 // uniquely identified by a combination of |type| and
92 // |id|. This approach is unable to distinguish networks with
93 // same name (e.g., different Wi-Fi networks with same SSID).
94 // This is a protected member to expose it to tests.
95 struct NET_EXPORT_PRIVATE NetworkID {
96 NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id)
97 : type(type), id(id) {}
98 NetworkID(const NetworkID& other) : type(other.type), id(other.id) {}
99 ~NetworkID() {}
101 NetworkID& operator=(const NetworkID& other) {
102 type = other.type;
103 id = other.id;
104 return *this;
107 // Overloaded because NetworkID is used as key in a map.
108 bool operator<(const NetworkID& other) const {
109 return type < other.type || (type == other.type && id < other.id);
112 // Connection type of the network.
113 NetworkChangeNotifier::ConnectionType type;
115 // Name of this network. This is set to:
116 // - Wi-Fi SSID if the device is connected to a Wi-Fi access point and the
117 // SSID name is available, or
118 // - MCC/MNC code of the cellular carrier if the device is connected to a
119 // cellular network, or
120 // - "Ethernet" in case the device is connected to ethernet.
121 // - An empty string in all other cases or if the network name is not
122 // exposed by platform APIs.
123 std::string id;
126 // Construct a NetworkQualityEstimator instance allowing for test
127 // configuration. Registers for network type change notifications so estimates
128 // can be kept network specific.
129 // |external_estimates_provider| may be NULL.
130 // |variation_params| is the map containing all field trial parameters for the
131 // network quality estimator field trial.
132 // |allow_local_host_requests_for_tests| should only be true when testing
133 // against local HTTP server and allows the requests to local host to be
134 // used for network quality estimation.
135 // |allow_smaller_responses_for_tests| should only be true when testing.
136 // Allows the responses smaller than |kMinTransferSizeInBytes| or shorter than
137 // |kMinRequestDurationMicroseconds| to be used for network quality
138 // estimation.
139 NetworkQualityEstimator(
140 scoped_ptr<ExternalEstimateProvider> external_estimates_provider,
141 const std::map<std::string, std::string>& variation_params,
142 bool allow_local_host_requests_for_tests,
143 bool allow_smaller_responses_for_tests);
145 // Returns true if the cached network quality estimate was successfully read.
146 bool ReadCachedNetworkQualityEstimate();
148 // NetworkChangeNotifier::ConnectionTypeObserver implementation:
149 void OnConnectionTypeChanged(
150 NetworkChangeNotifier::ConnectionType type) override;
152 // ExternalEstimateProvider::UpdatedEstimateObserver implementation.
153 void OnUpdatedEstimateAvailable() override;
155 private:
156 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
157 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestKbpsRTTUpdates);
158 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation);
159 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams);
160 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
161 FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, NetworkQualityEstimator);
162 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
163 PercentileSameTimestamps);
164 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
165 PercentileDifferentTimestamps);
166 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles);
167 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestCaching);
168 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
169 TestLRUCacheMaximumSize);
170 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMedianRTTSince);
171 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
172 TestExternalEstimateProvider);
173 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
174 TestExternalEstimateProviderMergeEstimates);
176 // NetworkQuality is used to cache the quality of a network connection.
177 class NET_EXPORT_PRIVATE NetworkQuality {
178 public:
179 NetworkQuality();
180 // |rtt| is the estimate of the round trip time.
181 // |downstream_throughput_kbps| is the estimate of the downstream
182 // throughput.
183 NetworkQuality(const base::TimeDelta& rtt,
184 int32_t downstream_throughput_kbps);
185 NetworkQuality(const NetworkQuality& other);
186 ~NetworkQuality();
188 NetworkQuality& operator=(const NetworkQuality& other);
190 // Returns the estimate of the round trip time.
191 const base::TimeDelta& rtt() const { return rtt_; }
193 // Returns the estimate of the downstream throughput in Kbps (Kilo bits per
194 // second).
195 int32_t downstream_throughput_kbps() const {
196 return downstream_throughput_kbps_;
199 private:
200 // Estimated round trip time.
201 base::TimeDelta rtt_;
203 // Estimated downstream throughput in Kbps.
204 int32_t downstream_throughput_kbps_;
207 // CachedNetworkQuality stores the quality of a previously seen network.
208 class NET_EXPORT_PRIVATE CachedNetworkQuality {
209 public:
210 explicit CachedNetworkQuality(const NetworkQuality& network_quality);
211 CachedNetworkQuality(const CachedNetworkQuality& other);
212 ~CachedNetworkQuality();
214 // Returns the network quality associated with this cached entry.
215 const NetworkQuality& network_quality() const { return network_quality_; }
217 // Returns true if this cache entry was updated before
218 // |cached_network_quality|.
219 bool OlderThan(const CachedNetworkQuality& cached_network_quality) const;
221 // Time when this cache entry was last updated.
222 const base::TimeTicks last_update_time_;
224 // Quality of this cached network.
225 const NetworkQuality network_quality_;
227 private:
228 DISALLOW_ASSIGN(CachedNetworkQuality);
231 // Records the round trip time or throughput observation, along with the time
232 // the observation was made.
233 struct NET_EXPORT_PRIVATE Observation {
234 Observation(int32_t value, base::TimeTicks timestamp);
235 ~Observation();
237 // Value of the observation.
238 const int32_t value;
240 // Time when the observation was taken.
241 const base::TimeTicks timestamp;
244 // Holds an observation and its weight.
245 struct NET_EXPORT_PRIVATE WeightedObservation {
246 WeightedObservation(int32_t value, double weight)
247 : value(value), weight(weight) {}
248 WeightedObservation(const WeightedObservation& other)
249 : WeightedObservation(other.value, other.weight) {}
251 WeightedObservation& operator=(const WeightedObservation& other) {
252 value = other.value;
253 weight = other.weight;
254 return *this;
257 // Required for sorting the samples in the ascending order of values.
258 bool operator<(const WeightedObservation& other) const {
259 return (value < other.value);
262 // Value of the sample.
263 int32_t value;
265 // Weight of the sample. This is computed based on how much time has passed
266 // since the sample was taken.
267 double weight;
270 // Stores observations sorted by time.
271 class NET_EXPORT_PRIVATE ObservationBuffer {
272 public:
273 explicit ObservationBuffer(double weight_multiplier_per_second);
274 ~ObservationBuffer();
276 // Adds |observation| to the buffer. The oldest observation in the buffer
277 // will be evicted to make room if the buffer is already full.
278 void AddObservation(const Observation& observation);
280 // Returns the number of observations in this buffer.
281 size_t Size() const;
283 // Clears the observations stored in this buffer.
284 void Clear();
286 // Returns true iff the |percentile| value of the observations in this
287 // buffer is available. Sets |result| to the computed |percentile|
288 // value among all observations since |begin_timestamp|. If the value is
289 // unavailable, false is returned and |result| is not modified. Percentile
290 // value is unavailable if all the values in observation buffer are older
291 // than |begin_timestamp|.
292 // |result| must not be null.
293 bool GetPercentile(const base::TimeTicks& begin_timestamp,
294 int32_t* result,
295 int percentile) const;
297 private:
298 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
299 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
300 ObtainOperatingParams);
301 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
303 // Computes the weighted observations and stores them in
304 // |weighted_observations| sorted by ascending |WeightedObservation.value|.
305 // Only the observations with timestamp later than |begin_timestamp| are
306 // considered. Also, sets |total_weight| to the total weight of all
307 // observations. Should be called only when there is at least one
308 // observation in the buffer.
309 void ComputeWeightedObservations(
310 const base::TimeTicks& begin_timestamp,
311 std::vector<WeightedObservation>& weighted_observations,
312 double* total_weight) const;
314 // Holds observations sorted by time, with the oldest observation at the
315 // front of the queue.
316 std::deque<Observation> observations_;
318 // The factor by which the weight of an observation reduces every second.
319 // For example, if an observation is 6 seconds old, its weight would be:
320 // weight_multiplier_per_second_ ^ 6
321 // Calculated from |kHalfLifeSeconds| by solving the following equation:
322 // weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5
323 const double weight_multiplier_per_second_;
325 DISALLOW_COPY_AND_ASSIGN(ObservationBuffer);
328 // This does not use a unordered_map or hash_map for code simplicity (key just
329 // implements operator<, rather than hash and equality) and because the map is
330 // tiny.
331 typedef std::map<NetworkID, CachedNetworkQuality> CachedNetworkQualities;
333 // Throughput is set to |kInvalidThroughput| if a valid value is
334 // unavailable. Readers should discard throughput value if it is set to
335 // |kInvalidThroughput|.
336 static const int32_t kInvalidThroughput;
338 // Tiny transfer sizes may give inaccurate throughput results.
339 // Minimum size of the transfer over which the throughput is computed.
340 static const int kMinTransferSizeInBytes = 10000;
342 // Minimum duration (in microseconds) of the transfer over which the
343 // throughput is computed.
344 static const int kMinRequestDurationMicroseconds = 1000;
346 // Minimum valid value of the variation parameter that holds RTT (in
347 // milliseconds) values.
348 static const int kMinimumRTTVariationParameterMsec = 1;
350 // Minimum valid value of the variation parameter that holds throughput (in
351 // kbps) values.
352 static const int kMinimumThroughputVariationParameterKbps = 1;
354 // Maximum size of the cache that holds network quality estimates.
355 // Smaller size may reduce the cache hit rate due to frequent evictions.
356 // Larger size may affect performance.
357 static const size_t kMaximumNetworkQualityCacheSize = 10;
359 // Maximum number of observations that can be held in the ObservationBuffer.
360 static const size_t kMaximumObservationsBufferSize = 300;
362 // Time duration (in milliseconds) after which the estimate provided by
363 // external estimate provider is considered stale.
364 static const int kExternalEstimateProviderFreshnessDurationMsec =
365 5 * 60 * 1000;
367 // Returns the RTT value to be used when the valid RTT is unavailable. Readers
368 // should discard RTT if it is set to the value returned by |InvalidRTT()|.
369 static const base::TimeDelta InvalidRTT();
371 // Queries the external estimate provider for the latest network quality
372 // estimates, and adds those estimates to the current observation buffer.
373 void QueryExternalEstimateProvider();
375 // Obtains operating parameters from the field trial parameters.
376 void ObtainOperatingParams(
377 const std::map<std::string, std::string>& variation_params);
379 // Adds the default median RTT and downstream throughput estimate for the
380 // current connection type to the observation buffer.
381 void AddDefaultEstimates();
383 // Returns an estimate of network quality at the specified |percentile|.
384 // Only the observations later than |begin_timestamp| are taken into account.
385 // |percentile| must be between 0 and 100 (both inclusive) with higher
386 // percentiles indicating less performant networks. For example, if
387 // |percentile| is 90, then the network is expected to be faster than the
388 // returned estimate with 0.9 probability. Similarly, network is expected to
389 // be slower than the returned estimate with 0.1 probability.
390 base::TimeDelta GetRTTEstimateInternal(const base::TimeTicks& begin_timestamp,
391 int percentile) const;
392 int32_t GetDownlinkThroughputKbpsEstimateInternal(
393 const base::TimeTicks& begin_timestamp,
394 int percentile) const;
396 // Returns the current network ID checking by calling the platform APIs.
397 // Virtualized for testing.
398 virtual NetworkID GetCurrentNetworkID() const;
400 // Writes the estimated quality of the current network to the cache.
401 void CacheNetworkQualityEstimate();
403 // Records the UMA related to RTT.
404 void RecordRTTUMA(int32_t estimated_value_msec,
405 int32_t actual_value_msec) const;
407 // Returns true only if |request| can be used for network quality estimation.
408 // Only the requests that go over network are considered to provide useful
409 // observations.
410 bool RequestProvidesUsefulObservations(const URLRequest& request) const;
412 // Values of external estimate provider status. This enum must remain
413 // synchronized with the enum of the same name in
414 // metrics/histograms/histograms.xml.
415 enum NQEExternalEstimateProviderStatus {
416 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE,
417 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE,
418 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED,
419 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL,
420 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK,
421 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY
424 // Records the metrics related to external estimate provider.
425 void RecordExternalEstimateProviderMetrics(
426 NQEExternalEstimateProviderStatus status) const;
428 // Determines if the requests to local host can be used in estimating the
429 // network quality. Set to true only for tests.
430 const bool allow_localhost_requests_;
432 // Determines if the responses smaller than |kMinTransferSizeInBytes|
433 // or shorter than |kMinTransferSizeInBytes| can be used in estimating the
434 // network quality. Set to true only for tests.
435 const bool allow_small_responses_;
437 // Time when last connection change was observed.
438 base::TimeTicks last_connection_change_;
440 // ID of the current network.
441 NetworkID current_network_id_;
443 // Peak network quality (fastest round-trip-time (RTT) and highest
444 // downstream throughput) measured since last connectivity change. RTT is
445 // measured from time the request is sent until the first byte received.
446 // The accuracy is decreased by ignoring these factors:
447 // 1) Multiple URLRequests can occur concurrently.
448 // 2) Includes server processing time.
449 NetworkQuality peak_network_quality_;
451 // Cache that stores quality of previously seen networks.
452 CachedNetworkQualities cached_network_qualities_;
454 // Buffer that holds Kbps observations sorted by timestamp.
455 ObservationBuffer downstream_throughput_kbps_observations_;
457 // Buffer that holds RTT (in milliseconds) observations sorted by timestamp.
458 ObservationBuffer rtt_msec_observations_;
460 // Default network quality observations obtained from the network quality
461 // estimator field trial parameters. The observations are indexed by
462 // ConnectionType.
463 NetworkQuality
464 default_observations_[NetworkChangeNotifier::CONNECTION_LAST + 1];
466 // Estimated network quality. Updated on mainframe requests.
467 NetworkQuality estimated_median_network_quality_;
469 // ExternalEstimateProvider that provides network quality using operating
470 // system APIs. May be NULL.
471 const scoped_ptr<ExternalEstimateProvider> external_estimate_provider_;
473 base::ThreadChecker thread_checker_;
475 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator);
478 } // namespace net
480 #endif // NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_