| OLD | NEW |
| (Empty) |
| 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. | |
| 4 | |
| 5 #ifndef NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_ | |
| 6 #define NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_ | |
| 7 | |
| 8 #include <stddef.h> | |
| 9 #include <stdint.h> | |
| 10 | |
| 11 #include <deque> | |
| 12 #include <map> | |
| 13 #include <string> | |
| 14 #include <tuple> | |
| 15 | |
| 16 #include "base/gtest_prod_util.h" | |
| 17 #include "base/macros.h" | |
| 18 #include "base/memory/ref_counted.h" | |
| 19 #include "base/memory/scoped_ptr.h" | |
| 20 #include "base/memory/weak_ptr.h" | |
| 21 #include "base/observer_list.h" | |
| 22 #include "base/threading/thread_checker.h" | |
| 23 #include "base/time/time.h" | |
| 24 #include "net/base/external_estimate_provider.h" | |
| 25 #include "net/base/net_export.h" | |
| 26 #include "net/base/network_change_notifier.h" | |
| 27 #include "net/base/socket_performance_watcher_factory.h" | |
| 28 | |
| 29 namespace base { | |
| 30 class SingleThreadTaskRunner; | |
| 31 } // namespace base | |
| 32 | |
| 33 namespace net { | |
| 34 | |
| 35 class URLRequest; | |
| 36 | |
| 37 // NetworkQualityEstimator provides network quality estimates (quality of the | |
| 38 // full paths to all origins that have been connected to). | |
| 39 // The estimates are based on the observed organic traffic. | |
| 40 // A NetworkQualityEstimator instance is attached to URLRequestContexts and | |
| 41 // observes the traffic of URLRequests spawned from the URLRequestContexts. | |
| 42 // A single instance of NQE can be attached to multiple URLRequestContexts, | |
| 43 // thereby increasing the single NQE instance's accuracy by providing more | |
| 44 // observed traffic characteristics. | |
| 45 class NET_EXPORT_PRIVATE NetworkQualityEstimator | |
| 46 : public NetworkChangeNotifier::ConnectionTypeObserver, | |
| 47 public ExternalEstimateProvider::UpdatedEstimateDelegate { | |
| 48 public: | |
| 49 // On Android, a Java counterpart will be generated for this enum. | |
| 50 // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.net | |
| 51 // GENERATED_JAVA_CLASS_NAME_OVERRIDE: NetworkQualityObservationSource | |
| 52 // GENERATED_JAVA_PREFIX_TO_STRIP: | |
| 53 enum ObservationSource { | |
| 54 // The observation was taken at the request layer, e.g., a round trip time | |
| 55 // is recorded as the time between the request being sent and the first byte | |
| 56 // being received. | |
| 57 URL_REQUEST, | |
| 58 // The observation is taken from TCP statistics maintained by the kernel. | |
| 59 TCP, | |
| 60 // The observation is taken at the QUIC layer. | |
| 61 QUIC, | |
| 62 // The observation is a previously cached estimate of the metric. | |
| 63 CACHED_ESTIMATE, | |
| 64 // The observation is derived from network connection information provided | |
| 65 // by the platform. For example, typical RTT and throughput values are used | |
| 66 // for a given type of network connection. | |
| 67 DEFAULT_FROM_PLATFORM, | |
| 68 // The observation came from a Chromium-external source. | |
| 69 EXTERNAL_ESTIMATE | |
| 70 }; | |
| 71 | |
| 72 // Observes measurements of round trip time. | |
| 73 class NET_EXPORT_PRIVATE RTTObserver { | |
| 74 public: | |
| 75 // Will be called when a new RTT observation is available. The round trip | |
| 76 // time is specified in milliseconds. The time when the observation was | |
| 77 // taken and the source of the observation are provided. | |
| 78 virtual void OnRTTObservation(int32_t rtt_ms, | |
| 79 const base::TimeTicks& timestamp, | |
| 80 ObservationSource source) = 0; | |
| 81 | |
| 82 protected: | |
| 83 RTTObserver() {} | |
| 84 virtual ~RTTObserver() {} | |
| 85 | |
| 86 private: | |
| 87 DISALLOW_COPY_AND_ASSIGN(RTTObserver); | |
| 88 }; | |
| 89 | |
| 90 // Observes measurements of throughput. | |
| 91 class NET_EXPORT_PRIVATE ThroughputObserver { | |
| 92 public: | |
| 93 // Will be called when a new throughput observation is available. | |
| 94 // Throughput is specified in kilobits per second. | |
| 95 virtual void OnThroughputObservation(int32_t throughput_kbps, | |
| 96 const base::TimeTicks& timestamp, | |
| 97 ObservationSource source) = 0; | |
| 98 | |
| 99 protected: | |
| 100 ThroughputObserver() {} | |
| 101 virtual ~ThroughputObserver() {} | |
| 102 | |
| 103 private: | |
| 104 DISALLOW_COPY_AND_ASSIGN(ThroughputObserver); | |
| 105 }; | |
| 106 | |
| 107 // Creates a new NetworkQualityEstimator. | |
| 108 // |variation_params| is the map containing all field trial parameters | |
| 109 // related to NetworkQualityEstimator field trial. | |
| 110 // |external_estimates_provider| may be NULL. | |
| 111 NetworkQualityEstimator( | |
| 112 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, | |
| 113 const std::map<std::string, std::string>& variation_params); | |
| 114 | |
| 115 // Construct a NetworkQualityEstimator instance allowing for test | |
| 116 // configuration. Registers for network type change notifications so estimates | |
| 117 // can be kept network specific. | |
| 118 // |external_estimates_provider| may be NULL. | |
| 119 // |variation_params| is the map containing all field trial parameters for the | |
| 120 // network quality estimator field trial. | |
| 121 // |allow_local_host_requests_for_tests| should only be true when testing | |
| 122 // against local HTTP server and allows the requests to local host to be | |
| 123 // used for network quality estimation. | |
| 124 // |allow_smaller_responses_for_tests| should only be true when testing. | |
| 125 // Allows the responses smaller than |kMinTransferSizeInBytes| or shorter than | |
| 126 // |kMinRequestDurationMicroseconds| to be used for network quality | |
| 127 // estimation. | |
| 128 NetworkQualityEstimator( | |
| 129 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, | |
| 130 const std::map<std::string, std::string>& variation_params, | |
| 131 bool allow_local_host_requests_for_tests, | |
| 132 bool allow_smaller_responses_for_tests); | |
| 133 | |
| 134 ~NetworkQualityEstimator() override; | |
| 135 | |
| 136 // Returns true if RTT is available and sets |rtt| to estimated RTT at the | |
| 137 // HTTP layer. Virtualized for testing. |rtt| should not be null. The RTT at | |
| 138 // the HTTP layer measures the time from when the request was sent (this | |
| 139 // happens after the connection is established) to the time when the response | |
| 140 // headers were received. | |
| 141 virtual bool GetURLRequestRTTEstimate(base::TimeDelta* rtt) const; | |
| 142 | |
| 143 // Returns true if downlink throughput is available and sets |kbps| to | |
| 144 // estimated downlink throughput (in kilobits per second). | |
| 145 // Virtualized for testing. |kbps| should not be null. | |
| 146 virtual bool GetDownlinkThroughputKbpsEstimate(int32_t* kbps) const; | |
| 147 | |
| 148 // Notifies NetworkQualityEstimator that the response header of |request| has | |
| 149 // been received. | |
| 150 void NotifyHeadersReceived(const URLRequest& request); | |
| 151 | |
| 152 // Notifies NetworkQualityEstimator that the response body of |request| has | |
| 153 // been received. | |
| 154 void NotifyRequestCompleted(const URLRequest& request); | |
| 155 | |
| 156 // Returns true if median RTT at the HTTP layer is available and sets |rtt| | |
| 157 // to the median of RTT observations since |begin_timestamp|. | |
| 158 // Virtualized for testing. |rtt| should not be null. The RTT at the HTTP | |
| 159 // layer measures the time from when the request was sent (this happens after | |
| 160 // the connection is established) to the time when the response headers were | |
| 161 // received. | |
| 162 virtual bool GetRecentURLRequestRTTMedian( | |
| 163 const base::TimeTicks& begin_timestamp, | |
| 164 base::TimeDelta* rtt) const; | |
| 165 | |
| 166 // Returns true if median downstream throughput is available and sets |kbps| | |
| 167 // to the median of downstream throughput (in kilobits per second) | |
| 168 // observations since |begin_timestamp|. Virtualized for testing. |kbps| | |
| 169 // should not be null. | |
| 170 virtual bool GetRecentMedianDownlinkThroughputKbps( | |
| 171 const base::TimeTicks& begin_timestamp, | |
| 172 int32_t* kbps) const; | |
| 173 | |
| 174 // Adds |rtt_observer| to the list of round trip time observers. Must be | |
| 175 // called on the IO thread. | |
| 176 void AddRTTObserver(RTTObserver* rtt_observer); | |
| 177 | |
| 178 // Removes |rtt_observer| from the list of round trip time observers if it | |
| 179 // is on the list of observers. Must be called on the IO thread. | |
| 180 void RemoveRTTObserver(RTTObserver* rtt_observer); | |
| 181 | |
| 182 // Adds |throughput_observer| to the list of throughput observers. Must be | |
| 183 // called on the IO thread. | |
| 184 void AddThroughputObserver(ThroughputObserver* throughput_observer); | |
| 185 | |
| 186 // Removes |throughput_observer| from the list of throughput observers if it | |
| 187 // is on the list of observers. Must be called on the IO thread. | |
| 188 void RemoveThroughputObserver(ThroughputObserver* throughput_observer); | |
| 189 | |
| 190 SocketPerformanceWatcherFactory* GetSocketPerformanceWatcherFactory(); | |
| 191 | |
| 192 protected: | |
| 193 // NetworkID is used to uniquely identify a network. | |
| 194 // For the purpose of network quality estimation and caching, a network is | |
| 195 // uniquely identified by a combination of |type| and | |
| 196 // |id|. This approach is unable to distinguish networks with | |
| 197 // same name (e.g., different Wi-Fi networks with same SSID). | |
| 198 // This is a protected member to expose it to tests. | |
| 199 struct NET_EXPORT_PRIVATE NetworkID { | |
| 200 NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id) | |
| 201 : type(type), id(id) {} | |
| 202 NetworkID(const NetworkID& other) : type(other.type), id(other.id) {} | |
| 203 ~NetworkID() {} | |
| 204 | |
| 205 NetworkID& operator=(const NetworkID& other) { | |
| 206 type = other.type; | |
| 207 id = other.id; | |
| 208 return *this; | |
| 209 } | |
| 210 | |
| 211 // Overloaded because NetworkID is used as key in a map. | |
| 212 bool operator<(const NetworkID& other) const { | |
| 213 return std::tie(type, id) < std::tie(other.type, other.id); | |
| 214 } | |
| 215 | |
| 216 // Connection type of the network. | |
| 217 NetworkChangeNotifier::ConnectionType type; | |
| 218 | |
| 219 // Name of this network. This is set to: | |
| 220 // - Wi-Fi SSID if the device is connected to a Wi-Fi access point and the | |
| 221 // SSID name is available, or | |
| 222 // - MCC/MNC code of the cellular carrier if the device is connected to a | |
| 223 // cellular network, or | |
| 224 // - "Ethernet" in case the device is connected to ethernet. | |
| 225 // - An empty string in all other cases or if the network name is not | |
| 226 // exposed by platform APIs. | |
| 227 std::string id; | |
| 228 }; | |
| 229 | |
| 230 // Returns true if the cached network quality estimate was successfully read. | |
| 231 bool ReadCachedNetworkQualityEstimate(); | |
| 232 | |
| 233 // NetworkChangeNotifier::ConnectionTypeObserver implementation: | |
| 234 void OnConnectionTypeChanged( | |
| 235 NetworkChangeNotifier::ConnectionType type) override; | |
| 236 | |
| 237 // ExternalEstimateProvider::UpdatedEstimateObserver implementation. | |
| 238 void OnUpdatedEstimateAvailable() override; | |
| 239 | |
| 240 private: | |
| 241 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations); | |
| 242 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestKbpsRTTUpdates); | |
| 243 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation); | |
| 244 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams); | |
| 245 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam); | |
| 246 FRIEND_TEST_ALL_PREFIXES(URLRequestTestHTTP, NetworkQualityEstimator); | |
| 247 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
| 248 PercentileSameTimestamps); | |
| 249 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
| 250 PercentileDifferentTimestamps); | |
| 251 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles); | |
| 252 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestCaching); | |
| 253 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
| 254 TestLRUCacheMaximumSize); | |
| 255 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMedianRTTSince); | |
| 256 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
| 257 TestExternalEstimateProvider); | |
| 258 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
| 259 TestExternalEstimateProviderMergeEstimates); | |
| 260 | |
| 261 class SocketWatcher; | |
| 262 class SocketWatcherFactory; | |
| 263 | |
| 264 // NetworkQuality is used to cache the quality of a network connection. | |
| 265 class NET_EXPORT_PRIVATE NetworkQuality { | |
| 266 public: | |
| 267 NetworkQuality(); | |
| 268 // |rtt| is the estimate of the round trip time. | |
| 269 // |downstream_throughput_kbps| is the estimate of the downstream | |
| 270 // throughput in kilobits per second. | |
| 271 NetworkQuality(const base::TimeDelta& rtt, | |
| 272 int32_t downstream_throughput_kbps); | |
| 273 NetworkQuality(const NetworkQuality& other); | |
| 274 ~NetworkQuality(); | |
| 275 | |
| 276 NetworkQuality& operator=(const NetworkQuality& other); | |
| 277 | |
| 278 // Returns the estimate of the round trip time. | |
| 279 const base::TimeDelta& rtt() const { return rtt_; } | |
| 280 | |
| 281 // Returns the estimate of the downstream throughput in Kbps (Kilobits per | |
| 282 // second). | |
| 283 int32_t downstream_throughput_kbps() const { | |
| 284 return downstream_throughput_kbps_; | |
| 285 } | |
| 286 | |
| 287 private: | |
| 288 // Estimated round trip time. | |
| 289 base::TimeDelta rtt_; | |
| 290 | |
| 291 // Estimated downstream throughput in kilobits per second. | |
| 292 int32_t downstream_throughput_kbps_; | |
| 293 }; | |
| 294 | |
| 295 // CachedNetworkQuality stores the quality of a previously seen network. | |
| 296 class NET_EXPORT_PRIVATE CachedNetworkQuality { | |
| 297 public: | |
| 298 explicit CachedNetworkQuality(const NetworkQuality& network_quality); | |
| 299 CachedNetworkQuality(const CachedNetworkQuality& other); | |
| 300 ~CachedNetworkQuality(); | |
| 301 | |
| 302 // Returns the network quality associated with this cached entry. | |
| 303 const NetworkQuality& network_quality() const { return network_quality_; } | |
| 304 | |
| 305 // Returns true if this cache entry was updated before | |
| 306 // |cached_network_quality|. | |
| 307 bool OlderThan(const CachedNetworkQuality& cached_network_quality) const; | |
| 308 | |
| 309 // Time when this cache entry was last updated. | |
| 310 const base::TimeTicks last_update_time_; | |
| 311 | |
| 312 // Quality of this cached network. | |
| 313 const NetworkQuality network_quality_; | |
| 314 | |
| 315 private: | |
| 316 DISALLOW_ASSIGN(CachedNetworkQuality); | |
| 317 }; | |
| 318 | |
| 319 // Records observations of network quality metrics (such as round trip time | |
| 320 // or throughput), along with the time the observation was made. Observations | |
| 321 // can be made at several places in the network stack, thus the observation | |
| 322 // source is provided as well. ValueType must be numerical so that statistics | |
| 323 // such as median, average can be computed. | |
| 324 template <typename ValueType> | |
| 325 struct NET_EXPORT_PRIVATE Observation { | |
| 326 Observation(const ValueType& value, | |
| 327 base::TimeTicks timestamp, | |
| 328 ObservationSource source) | |
| 329 : value(value), timestamp(timestamp), source(source) { | |
| 330 DCHECK(!timestamp.is_null()); | |
| 331 } | |
| 332 ~Observation() {} | |
| 333 | |
| 334 // Value of the observation. | |
| 335 const ValueType value; | |
| 336 | |
| 337 // Time when the observation was taken. | |
| 338 const base::TimeTicks timestamp; | |
| 339 | |
| 340 // The source of the observation. | |
| 341 const ObservationSource source; | |
| 342 }; | |
| 343 | |
| 344 // Holds an observation and its weight. | |
| 345 template <typename ValueType> | |
| 346 struct NET_EXPORT_PRIVATE WeightedObservation { | |
| 347 WeightedObservation(ValueType value, double weight) | |
| 348 : value(value), weight(weight) {} | |
| 349 WeightedObservation(const WeightedObservation& other) | |
| 350 : WeightedObservation(other.value, other.weight) {} | |
| 351 | |
| 352 WeightedObservation& operator=(const WeightedObservation& other) { | |
| 353 value = other.value; | |
| 354 weight = other.weight; | |
| 355 return *this; | |
| 356 } | |
| 357 | |
| 358 // Required for sorting the samples in the ascending order of values. | |
| 359 bool operator<(const WeightedObservation& other) const { | |
| 360 return (value < other.value); | |
| 361 } | |
| 362 | |
| 363 // Value of the sample. | |
| 364 ValueType value; | |
| 365 | |
| 366 // Weight of the sample. This is computed based on how much time has passed | |
| 367 // since the sample was taken. | |
| 368 double weight; | |
| 369 }; | |
| 370 | |
| 371 // Stores observations sorted by time. | |
| 372 template <typename ValueType> | |
| 373 class NET_EXPORT_PRIVATE ObservationBuffer { | |
| 374 public: | |
| 375 explicit ObservationBuffer(double weight_multiplier_per_second); | |
| 376 ~ObservationBuffer(); | |
| 377 | |
| 378 // Adds |observation| to the buffer. The oldest observation in the buffer | |
| 379 // will be evicted to make room if the buffer is already full. | |
| 380 void AddObservation(const Observation<ValueType>& observation) { | |
| 381 DCHECK_LE(observations_.size(), | |
| 382 static_cast<size_t>(kMaximumObservationsBufferSize)); | |
| 383 // Evict the oldest element if the buffer is already full. | |
| 384 if (observations_.size() == kMaximumObservationsBufferSize) | |
| 385 observations_.pop_front(); | |
| 386 | |
| 387 observations_.push_back(observation); | |
| 388 DCHECK_LE(observations_.size(), | |
| 389 static_cast<size_t>(kMaximumObservationsBufferSize)); | |
| 390 } | |
| 391 | |
| 392 // Returns the number of observations in this buffer. | |
| 393 size_t Size() const { return observations_.size(); } | |
| 394 | |
| 395 // Clears the observations stored in this buffer. | |
| 396 void Clear() { observations_.clear(); } | |
| 397 | |
| 398 // Returns true iff the |percentile| value of the observations in this | |
| 399 // buffer is available. Sets |result| to the computed |percentile| | |
| 400 // value among all observations since |begin_timestamp|. If the value is | |
| 401 // unavailable, false is returned and |result| is not modified. Percentile | |
| 402 // value is unavailable if all the values in observation buffer are older | |
| 403 // than |begin_timestamp|. |result| must not be null. | |
| 404 // |disallowed_observation_sources| is the list of observation sources that | |
| 405 // should be excluded when computing the percentile. | |
| 406 bool GetPercentile(const base::TimeTicks& begin_timestamp, | |
| 407 ValueType* result, | |
| 408 int percentile, | |
| 409 const std::vector<ObservationSource>& | |
| 410 disallowed_observation_sources) const; | |
| 411 | |
| 412 private: | |
| 413 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations); | |
| 414 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
| 415 ObtainOperatingParams); | |
| 416 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam); | |
| 417 | |
| 418 // Computes the weighted observations and stores them in | |
| 419 // |weighted_observations| sorted by ascending |WeightedObservation.value|. | |
| 420 // Only the observations with timestamp later than |begin_timestamp| are | |
| 421 // considered. Also, sets |total_weight| to the total weight of all | |
| 422 // observations. Should be called only when there is at least one | |
| 423 // observation in the buffer. |disallowed_observation_sources| is the list | |
| 424 // of observation sources that should be excluded when computing the | |
| 425 // weighted observations. | |
| 426 void ComputeWeightedObservations( | |
| 427 const base::TimeTicks& begin_timestamp, | |
| 428 std::vector<WeightedObservation<ValueType>>& weighted_observations, | |
| 429 double* total_weight, | |
| 430 const std::vector<ObservationSource>& disallowed_observation_sources) | |
| 431 const; | |
| 432 | |
| 433 // Holds observations sorted by time, with the oldest observation at the | |
| 434 // front of the queue. | |
| 435 std::deque<Observation<ValueType>> observations_; | |
| 436 | |
| 437 // The factor by which the weight of an observation reduces every second. | |
| 438 // For example, if an observation is 6 seconds old, its weight would be: | |
| 439 // weight_multiplier_per_second_ ^ 6 | |
| 440 // Calculated from |kHalfLifeSeconds| by solving the following equation: | |
| 441 // weight_multiplier_per_second_ ^ kHalfLifeSeconds = 0.5 | |
| 442 const double weight_multiplier_per_second_; | |
| 443 | |
| 444 DISALLOW_COPY_AND_ASSIGN(ObservationBuffer); | |
| 445 }; | |
| 446 | |
| 447 // Value of round trip time observations is in base::TimeDelta. | |
| 448 typedef net::NetworkQualityEstimator::Observation<base::TimeDelta> | |
| 449 RttObservation; | |
| 450 typedef net::NetworkQualityEstimator::ObservationBuffer<base::TimeDelta> | |
| 451 RttObservationBuffer; | |
| 452 | |
| 453 // Value of throughput observations is in kilobits per second. | |
| 454 typedef net::NetworkQualityEstimator::Observation<int32_t> | |
| 455 ThroughputObservation; | |
| 456 typedef net::NetworkQualityEstimator::ObservationBuffer<int32_t> | |
| 457 ThroughputObservationBuffer; | |
| 458 | |
| 459 // This does not use a unordered_map or hash_map for code simplicity (key just | |
| 460 // implements operator<, rather than hash and equality) and because the map is | |
| 461 // tiny. | |
| 462 typedef std::map<NetworkID, CachedNetworkQuality> CachedNetworkQualities; | |
| 463 | |
| 464 // Throughput is set to |kInvalidThroughput| if a valid value is | |
| 465 // unavailable. Readers should discard throughput value if it is set to | |
| 466 // |kInvalidThroughput|. | |
| 467 static const int32_t kInvalidThroughput; | |
| 468 | |
| 469 // Tiny transfer sizes may give inaccurate throughput results. | |
| 470 // Minimum size of the transfer over which the throughput is computed. | |
| 471 static const int kMinTransferSizeInBytes = 10000; | |
| 472 | |
| 473 // Minimum duration (in microseconds) of the transfer over which the | |
| 474 // throughput is computed. | |
| 475 static const int kMinRequestDurationMicroseconds = 1000; | |
| 476 | |
| 477 // Minimum valid value of the variation parameter that holds RTT (in | |
| 478 // milliseconds) values. | |
| 479 static const int kMinimumRTTVariationParameterMsec = 1; | |
| 480 | |
| 481 // Minimum valid value of the variation parameter that holds throughput (in | |
| 482 // kilobits per second) values. | |
| 483 static const int kMinimumThroughputVariationParameterKbps = 1; | |
| 484 | |
| 485 // Maximum size of the cache that holds network quality estimates. | |
| 486 // Smaller size may reduce the cache hit rate due to frequent evictions. | |
| 487 // Larger size may affect performance. | |
| 488 static const size_t kMaximumNetworkQualityCacheSize = 10; | |
| 489 | |
| 490 // Maximum number of observations that can be held in the ObservationBuffer. | |
| 491 static const size_t kMaximumObservationsBufferSize = 300; | |
| 492 | |
| 493 // Time duration (in milliseconds) after which the estimate provided by | |
| 494 // external estimate provider is considered stale. | |
| 495 static const int kExternalEstimateProviderFreshnessDurationMsec = | |
| 496 5 * 60 * 1000; | |
| 497 | |
| 498 // Returns the RTT value to be used when the valid RTT is unavailable. Readers | |
| 499 // should discard RTT if it is set to the value returned by |InvalidRTT()|. | |
| 500 static const base::TimeDelta InvalidRTT(); | |
| 501 | |
| 502 // Notifies |this| of a new transport layer RTT. | |
| 503 void OnUpdatedRTTAvailable(SocketPerformanceWatcherFactory::Protocol protocol, | |
| 504 const base::TimeDelta& rtt); | |
| 505 | |
| 506 // Queries the external estimate provider for the latest network quality | |
| 507 // estimates, and adds those estimates to the current observation buffer. | |
| 508 void QueryExternalEstimateProvider(); | |
| 509 | |
| 510 // Obtains operating parameters from the field trial parameters. | |
| 511 void ObtainOperatingParams( | |
| 512 const std::map<std::string, std::string>& variation_params); | |
| 513 | |
| 514 // Adds the default median RTT and downstream throughput estimate for the | |
| 515 // current connection type to the observation buffer. | |
| 516 void AddDefaultEstimates(); | |
| 517 | |
| 518 // Returns an estimate of network quality at the specified |percentile|. | |
| 519 // Only the observations later than |begin_timestamp| are taken into account. | |
| 520 // |percentile| must be between 0 and 100 (both inclusive) with higher | |
| 521 // percentiles indicating less performant networks. For example, if | |
| 522 // |percentile| is 90, then the network is expected to be faster than the | |
| 523 // returned estimate with 0.9 probability. Similarly, network is expected to | |
| 524 // be slower than the returned estimate with 0.1 probability. | |
| 525 base::TimeDelta GetURLRequestRTTEstimateInternal( | |
| 526 const base::TimeTicks& begin_timestamp, | |
| 527 int percentile) const; | |
| 528 int32_t GetDownlinkThroughputKbpsEstimateInternal( | |
| 529 const base::TimeTicks& begin_timestamp, | |
| 530 int percentile) const; | |
| 531 | |
| 532 // Returns the current network ID checking by calling the platform APIs. | |
| 533 // Virtualized for testing. | |
| 534 virtual NetworkID GetCurrentNetworkID() const; | |
| 535 | |
| 536 // Writes the estimated quality of the current network to the cache. | |
| 537 void CacheNetworkQualityEstimate(); | |
| 538 | |
| 539 void NotifyObserversOfRTT(const RttObservation& observation); | |
| 540 | |
| 541 void NotifyObserversOfThroughput(const ThroughputObservation& observation); | |
| 542 | |
| 543 // Records the UMA related to RTT. | |
| 544 void RecordRTTUMA(int32_t estimated_value_msec, | |
| 545 int32_t actual_value_msec) const; | |
| 546 | |
| 547 // Returns true only if |request| can be used for network quality estimation. | |
| 548 // Only the requests that go over network are considered to provide useful | |
| 549 // observations. | |
| 550 bool RequestProvidesUsefulObservations(const URLRequest& request) const; | |
| 551 | |
| 552 // Values of external estimate provider status. This enum must remain | |
| 553 // synchronized with the enum of the same name in | |
| 554 // metrics/histograms/histograms.xml. | |
| 555 enum NQEExternalEstimateProviderStatus { | |
| 556 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE, | |
| 557 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE, | |
| 558 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED, | |
| 559 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL, | |
| 560 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK, | |
| 561 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY | |
| 562 }; | |
| 563 | |
| 564 // Records the metrics related to external estimate provider. | |
| 565 void RecordExternalEstimateProviderMetrics( | |
| 566 NQEExternalEstimateProviderStatus status) const; | |
| 567 | |
| 568 // Determines if the requests to local host can be used in estimating the | |
| 569 // network quality. Set to true only for tests. | |
| 570 const bool allow_localhost_requests_; | |
| 571 | |
| 572 // Determines if the responses smaller than |kMinTransferSizeInBytes| | |
| 573 // or shorter than |kMinTransferSizeInBytes| can be used in estimating the | |
| 574 // network quality. Set to true only for tests. | |
| 575 const bool allow_small_responses_; | |
| 576 | |
| 577 // Time when last connection change was observed. | |
| 578 base::TimeTicks last_connection_change_; | |
| 579 | |
| 580 // ID of the current network. | |
| 581 NetworkID current_network_id_; | |
| 582 | |
| 583 // Peak network quality (fastest round-trip-time (RTT) and highest | |
| 584 // downstream throughput) measured since last connectivity change. RTT is | |
| 585 // measured from time the request is sent until the first byte received. | |
| 586 // The accuracy is decreased by ignoring these factors: | |
| 587 // 1) Multiple URLRequests can occur concurrently. | |
| 588 // 2) Includes server processing time. | |
| 589 NetworkQuality peak_network_quality_; | |
| 590 | |
| 591 // Cache that stores quality of previously seen networks. | |
| 592 CachedNetworkQualities cached_network_qualities_; | |
| 593 | |
| 594 // Buffer that holds throughput observations (in kilobits per second) sorted | |
| 595 // by timestamp. | |
| 596 ThroughputObservationBuffer downstream_throughput_kbps_observations_; | |
| 597 | |
| 598 // Buffer that holds RTT observations sorted by timestamp. | |
| 599 RttObservationBuffer rtt_observations_; | |
| 600 | |
| 601 // Default network quality observations obtained from the network quality | |
| 602 // estimator field trial parameters. The observations are indexed by | |
| 603 // ConnectionType. | |
| 604 NetworkQuality | |
| 605 default_observations_[NetworkChangeNotifier::CONNECTION_LAST + 1]; | |
| 606 | |
| 607 // Estimated network quality. Updated on mainframe requests. | |
| 608 NetworkQuality estimated_median_network_quality_; | |
| 609 | |
| 610 // ExternalEstimateProvider that provides network quality using operating | |
| 611 // system APIs. May be NULL. | |
| 612 const scoped_ptr<ExternalEstimateProvider> external_estimate_provider_; | |
| 613 | |
| 614 // Observer lists for round trip times and throughput measurements. | |
| 615 base::ObserverList<RTTObserver> rtt_observer_list_; | |
| 616 base::ObserverList<ThroughputObserver> throughput_observer_list_; | |
| 617 | |
| 618 scoped_ptr<SocketPerformanceWatcherFactory> watcher_factory_; | |
| 619 | |
| 620 base::ThreadChecker thread_checker_; | |
| 621 | |
| 622 base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_; | |
| 623 | |
| 624 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator); | |
| 625 }; | |
| 626 | |
| 627 } // namespace net | |
| 628 | |
| 629 #endif // NET_BASE_NETWORK_QUALITY_ESTIMATOR_H_ | |
| OLD | NEW |