Pin Chrome's shortcut to the Win10 Start menu on install and OS upgrade.
[chromium-blink-merge.git] / net / base / network_quality_estimator.h
blobdadce886e93624982efc1af620701e04912fc3c1
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"
21 #include "net/base/network_quality.h"
23 namespace net {
25 // NetworkQualityEstimator provides network quality estimates (quality of the
26 // full paths to all origins that have been connected to).
27 // The estimates are based on the observed organic traffic.
28 // A NetworkQualityEstimator instance is attached to URLRequestContexts and
29 // observes the traffic of URLRequests spawned from the URLRequestContexts.
30 // A single instance of NQE can be attached to multiple URLRequestContexts,
31 // thereby increasing the single NQE instance's accuracy by providing more
32 // observed traffic characteristics.
33 class NET_EXPORT_PRIVATE NetworkQualityEstimator
34 : public NetworkChangeNotifier::ConnectionTypeObserver {
35 public:
36 // Creates a new NetworkQualityEstimator.
37 // |variation_params| is the map containing all field trial parameters
38 // related to NetworkQualityEstimator field trial.
39 explicit NetworkQualityEstimator(
40 const std::map<std::string, std::string>& variation_params);
42 ~NetworkQualityEstimator() override;
44 // Returns the peak estimates (fastest RTT and peak throughput) of the
45 // current network.
46 // Virtualized for testing.
47 virtual NetworkQuality GetPeakEstimate() const;
49 // Sets |median| to the estimate of median network quality. The estimated
50 // quality is computed using a weighted median algorithm that assigns higher
51 // weight to the recent observations. |median| must not be nullptr. Returns
52 // true only if an estimate of the network quality is available (enough
53 // observations must be available to make an estimate). Virtualized for
54 // testing. If the estimate is not available, |median| is set to the default
55 // value.
56 virtual bool GetEstimate(NetworkQuality* median) const;
58 // Notifies NetworkQualityEstimator that a response has been received.
59 // |cumulative_prefilter_bytes_read| is the count of the bytes received prior
60 // to applying filters (e.g. decompression, SDCH) from request creation time
61 // until now.
62 // |prefiltered_bytes_read| is the count of the bytes received prior
63 // to applying filters in the most recent read.
64 void NotifyDataReceived(const URLRequest& request,
65 int64_t cumulative_prefilter_bytes_read,
66 int64_t prefiltered_bytes_read);
68 protected:
69 // NetworkID is used to uniquely identify a network.
70 // For the purpose of network quality estimation and caching, a network is
71 // uniquely identified by a combination of |type| and
72 // |id|. This approach is unable to distinguish networks with
73 // same name (e.g., different Wi-Fi networks with same SSID).
74 // This is a protected member to expose it to tests.
75 struct NET_EXPORT_PRIVATE NetworkID {
76 NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id)
77 : type(type), id(id) {}
78 NetworkID(const NetworkID& other) : type(other.type), id(other.id) {}
79 ~NetworkID() {}
81 NetworkID& operator=(const NetworkID& other) {
82 type = other.type;
83 id = other.id;
84 return *this;
87 // Overloaded because NetworkID is used as key in a map.
88 bool operator<(const NetworkID& other) const {
89 return type < other.type || (type == other.type && id < other.id);
92 // Connection type of the network.
93 NetworkChangeNotifier::ConnectionType type;
95 // Name of this network. This is set to:
96 // - Wi-Fi SSID if the device is connected to a Wi-Fi access point and the
97 // SSID name is available, or
98 // - MCC/MNC code of the cellular carrier if the device is connected to a
99 // cellular network, or
100 // - "Ethernet" in case the device is connected to ethernet.
101 // - An empty string in all other cases or if the network name is not
102 // exposed by platform APIs.
103 std::string id;
106 // Construct a NetworkQualityEstimator instance allowing for test
107 // configuration. Registers for network type change notifications so estimates
108 // can be kept network specific.
109 // |variation_params| is the map containing all field trial parameters for the
110 // network quality estimator field trial.
111 // |allow_local_host_requests_for_tests| should only be true when testing
112 // against local HTTP server and allows the requests to local host to be
113 // used for network quality estimation.
114 // |allow_smaller_responses_for_tests| should only be true when testing.
115 // Allows the responses smaller than |kMinTransferSizeInBytes| or shorter than
116 // |kMinRequestDurationMicroseconds| to be used for network quality
117 // estimation.
118 NetworkQualityEstimator(
119 const std::map<std::string, std::string>& variation_params,
120 bool allow_local_host_requests_for_tests,
121 bool allow_smaller_responses_for_tests);
123 // Returns true if the cached network quality estimate was successfully read.
124 bool ReadCachedNetworkQualityEstimate();
126 // NetworkChangeNotifier::ConnectionTypeObserver implementation.
127 void OnConnectionTypeChanged(
128 NetworkChangeNotifier::ConnectionType type) override;
130 private:
131 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
132 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestKbpsRTTUpdates);
133 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation);
134 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams);
135 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
136 FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, NetworkQualityEstimator);
137 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
138 PercentileSameTimestamps);
139 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
140 PercentileDifferentTimestamps);
141 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles);
142 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestCaching);
143 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
144 TestLRUCacheMaximumSize);
146 // CachedNetworkQuality stores the quality of a previously seen network.
147 class NET_EXPORT_PRIVATE CachedNetworkQuality {
148 public:
149 explicit CachedNetworkQuality(const NetworkQuality& network_quality);
150 CachedNetworkQuality(const CachedNetworkQuality& other);
151 ~CachedNetworkQuality();
153 // Returns the network quality associated with this cached entry.
154 const NetworkQuality network_quality() const { return network_quality_; }
156 // Returns true if this cache entry was updated before
157 // |cached_network_quality|.
158 bool OlderThan(const CachedNetworkQuality& cached_network_quality) const;
160 // Time when this cache entry was last updated.
161 const base::TimeTicks last_update_time_;
163 // Quality of this cached network.
164 const NetworkQuality network_quality_;
166 private:
167 DISALLOW_ASSIGN(CachedNetworkQuality);
170 // Records the round trip time or throughput observation, along with the time
171 // the observation was made.
172 struct NET_EXPORT_PRIVATE Observation {
173 Observation(int32_t value, base::TimeTicks timestamp);
174 ~Observation();
176 // Value of the observation.
177 const int32_t value;
179 // Time when the observation was taken.
180 const base::TimeTicks timestamp;
183 // Holds an observation and its weight.
184 struct NET_EXPORT_PRIVATE WeightedObservation {
185 WeightedObservation(int32_t value, double weight)
186 : value(value), weight(weight) {}
187 WeightedObservation(const WeightedObservation& other)
188 : WeightedObservation(other.value, other.weight) {}
190 WeightedObservation& operator=(const WeightedObservation& other) {
191 value = other.value;
192 weight = other.weight;
193 return *this;
196 // Required for sorting the samples in the ascending order of values.
197 bool operator<(const WeightedObservation& other) const {
198 return (value < other.value);
201 // Value of the sample.
202 int32_t value;
204 // Weight of the sample. This is computed based on how much time has passed
205 // since the sample was taken.
206 double weight;
209 // Stores observations sorted by time.
210 class NET_EXPORT_PRIVATE ObservationBuffer {
211 public:
212 explicit ObservationBuffer(double weight_multiplier_per_second);
213 ~ObservationBuffer();
215 // Adds |observation| to the buffer. The oldest observation in the buffer
216 // will be evicted to make room if the buffer is already full.
217 void AddObservation(const Observation& observation);
219 // Returns the number of observations in this buffer.
220 size_t Size() const;
222 // Clears the observations stored in this buffer.
223 void Clear();
225 // Returns the |percentile| value of the observations in this buffer.
226 int32_t GetPercentile(int percentile) const;
228 private:
229 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations);
230 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest,
231 ObtainOperatingParams);
232 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam);
234 // Computes the weighted observations and stores them in
235 // |weighted_observations| sorted by ascending |WeightedObservation.value|.
236 // Sets |total_weight| to the total weight of all observations. Should be
237 // called only when there is at least one observation in the buffer.
238 void ComputeWeightedObservations(
239 std::vector<WeightedObservation>& weighted_observations,
240 double* total_weight) const;
242 // Holds observations sorted by time, with the oldest observation at the
243 // front of the queue.
244 std::deque<Observation> observations_;
246 // The factor by which the weight of an observation reduces every second.
247 // For example, if an observation is 6 seconds old, its weight would be:
248 // weight_multiplier_per_second_ ^ 6
249 // Calculated from |kHalfLifeSeconds| by solving the following equation:
250 // weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5
251 const double weight_multiplier_per_second_;
253 DISALLOW_COPY_AND_ASSIGN(ObservationBuffer);
256 // This does not use a unordered_map or hash_map for code simplicity (key just
257 // implements operator<, rather than hash and equality) and because the map is
258 // tiny.
259 typedef std::map<NetworkID, CachedNetworkQuality> CachedNetworkQualities;
261 // Tiny transfer sizes may give inaccurate throughput results.
262 // Minimum size of the transfer over which the throughput is computed.
263 static const int kMinTransferSizeInBytes = 10000;
265 // Minimum duration (in microseconds) of the transfer over which the
266 // throughput is computed.
267 static const int kMinRequestDurationMicroseconds = 1000;
269 // Minimum valid value of the variation parameter that holds RTT (in
270 // milliseconds) values.
271 static const int kMinimumRTTVariationParameterMsec = 1;
273 // Minimum valid value of the variation parameter that holds throughput (in
274 // kbps) values.
275 static const int kMinimumThroughputVariationParameterKbps = 1;
277 // Maximum size of the cache that holds network quality estimates.
278 // Smaller size may reduce the cache hit rate due to frequent evictions.
279 // Larger size may affect performance.
280 static const size_t kMaximumNetworkQualityCacheSize = 10;
282 // Maximum number of observations that can be held in the ObservationBuffer.
283 static const size_t kMaximumObservationsBufferSize = 300;
285 // Obtains operating parameters from the field trial parameters.
286 void ObtainOperatingParams(
287 const std::map<std::string, std::string>& variation_params);
289 // Adds the default median RTT and downstream throughput estimate for the
290 // current connection type to the observation buffer.
291 void AddDefaultEstimates();
293 // Returns an estimate of network quality at the specified |percentile|.
294 // |percentile| must be between 0 and 100 (both inclusive) with higher
295 // percentiles indicating less performant networks. For example, if
296 // |percentile| is 90, then the network is expected to be faster than the
297 // returned estimate with 0.9 probability. Similarly, network is expected to
298 // be slower than the returned estimate with 0.1 probability.
299 NetworkQuality GetEstimate(int percentile) const;
301 // Returns the current network ID checking by calling the platform APIs.
302 // Virtualized for testing.
303 virtual NetworkID GetCurrentNetworkID() const;
305 // Writes the estimated quality of the current network to the cache.
306 void CacheNetworkQualityEstimate();
308 // Records the UMA related to RTT.
309 void RecordRTTUMA(int32_t estimated_value_msec,
310 int32_t actual_value_msec) const;
312 // Determines if the requests to local host can be used in estimating the
313 // network quality. Set to true only for tests.
314 const bool allow_localhost_requests_;
316 // Determines if the responses smaller than |kMinTransferSizeInBytes|
317 // or shorter than |kMinTransferSizeInBytes| can be used in estimating the
318 // network quality. Set to true only for tests.
319 const bool allow_small_responses_;
321 // Time when last connection change was observed.
322 base::TimeTicks last_connection_change_;
324 // ID of the current network.
325 NetworkID current_network_id_;
327 // Peak network quality (fastest round-trip-time (RTT) and highest
328 // downstream throughput) measured since last connectivity change. RTT is
329 // measured from time the request is sent until the first byte received.
330 // The accuracy is decreased by ignoring these factors:
331 // 1) Multiple URLRequests can occur concurrently.
332 // 2) Includes server processing time.
333 NetworkQuality peak_network_quality_;
335 // Cache that stores quality of previously seen networks.
336 CachedNetworkQualities cached_network_qualities_;
338 // Buffer that holds Kbps observations sorted by timestamp.
339 ObservationBuffer kbps_observations_;
341 // Buffer that holds RTT (in milliseconds) observations sorted by timestamp.
342 ObservationBuffer rtt_msec_observations_;
344 // Default network quality observations obtained from the network quality
345 // estimator field trial parameters. The observations are indexed by
346 // ConnectionType.
347 NetworkQuality
348 default_observations_[NetworkChangeNotifier::CONNECTION_LAST + 1];
350 // Estimated network quality. Updated on mainframe requests.
351 NetworkQuality estimated_median_network_quality_;
353 base::ThreadChecker thread_checker_;
355 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator);
358 } // namespace net
360 #endif // NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_