OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ | 5 #ifndef NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ |
6 #define NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ | 6 #define NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ |
7 | 7 |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <map> | 10 #include <map> |
11 #include <memory> | 11 #include <memory> |
12 #include <string> | 12 #include <string> |
13 #include <tuple> | |
14 | 13 |
15 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
16 #include "base/gtest_prod_util.h" | 15 #include "base/gtest_prod_util.h" |
17 #include "base/macros.h" | 16 #include "base/macros.h" |
18 #include "base/memory/ref_counted.h" | 17 #include "base/memory/ref_counted.h" |
19 #include "base/memory/weak_ptr.h" | 18 #include "base/memory/weak_ptr.h" |
20 #include "base/observer_list.h" | 19 #include "base/observer_list.h" |
21 #include "base/threading/thread_checker.h" | 20 #include "base/threading/thread_checker.h" |
22 #include "base/time/time.h" | 21 #include "base/time/time.h" |
23 #include "net/base/net_export.h" | 22 #include "net/base/net_export.h" |
24 #include "net/base/network_change_notifier.h" | 23 #include "net/base/network_change_notifier.h" |
25 #include "net/nqe/cached_network_quality.h" | 24 #include "net/nqe/cached_network_quality.h" |
26 #include "net/nqe/external_estimate_provider.h" | 25 #include "net/nqe/external_estimate_provider.h" |
| 26 #include "net/nqe/network_id.h" |
27 #include "net/nqe/network_quality.h" | 27 #include "net/nqe/network_quality.h" |
28 #include "net/nqe/network_quality_observation.h" | 28 #include "net/nqe/network_quality_observation.h" |
29 #include "net/nqe/network_quality_observation_source.h" | 29 #include "net/nqe/network_quality_observation_source.h" |
| 30 #include "net/nqe/network_quality_store.h" |
30 #include "net/nqe/observation_buffer.h" | 31 #include "net/nqe/observation_buffer.h" |
31 #include "net/socket/socket_performance_watcher_factory.h" | 32 #include "net/socket/socket_performance_watcher_factory.h" |
32 | 33 |
33 namespace base { | 34 namespace base { |
34 class TickClock; | 35 class TickClock; |
35 } // namespace base | 36 } // namespace base |
36 | 37 |
37 namespace net { | 38 namespace net { |
38 | 39 |
39 namespace nqe { | 40 namespace nqe { |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
236 // Allows the responses smaller than |kMinTransferSizeInBits| to be used for | 237 // Allows the responses smaller than |kMinTransferSizeInBits| to be used for |
237 // network quality estimation. | 238 // network quality estimation. |
238 void SetUseSmallResponsesForTesting(bool use_small_responses); | 239 void SetUseSmallResponsesForTesting(bool use_small_responses); |
239 | 240 |
240 // Reports |effective_connection_type| to all | 241 // Reports |effective_connection_type| to all |
241 // EffectiveConnectionTypeObservers. | 242 // EffectiveConnectionTypeObservers. |
242 void ReportEffectiveConnectionTypeForTesting( | 243 void ReportEffectiveConnectionTypeForTesting( |
243 EffectiveConnectionType effective_connection_type); | 244 EffectiveConnectionType effective_connection_type); |
244 | 245 |
245 protected: | 246 protected: |
246 // NetworkID is used to uniquely identify a network. | |
247 // For the purpose of network quality estimation and caching, a network is | |
248 // uniquely identified by a combination of |type| and | |
249 // |id|. This approach is unable to distinguish networks with | |
250 // same name (e.g., different Wi-Fi networks with same SSID). | |
251 // This is a protected member to expose it to tests. | |
252 struct NET_EXPORT_PRIVATE NetworkID { | |
253 NetworkID(NetworkChangeNotifier::ConnectionType type, const std::string& id) | |
254 : type(type), id(id) {} | |
255 NetworkID(const NetworkID& other) : type(other.type), id(other.id) {} | |
256 ~NetworkID() {} | |
257 | |
258 NetworkID& operator=(const NetworkID& other) { | |
259 type = other.type; | |
260 id = other.id; | |
261 return *this; | |
262 } | |
263 | |
264 // Overloaded because NetworkID is used as key in a map. | |
265 bool operator<(const NetworkID& other) const { | |
266 return std::tie(type, id) < std::tie(other.type, other.id); | |
267 } | |
268 | |
269 // Connection type of the network. | |
270 NetworkChangeNotifier::ConnectionType type; | |
271 | |
272 // Name of this network. This is set to: | |
273 // - Wi-Fi SSID if the device is connected to a Wi-Fi access point and the | |
274 // SSID name is available, or | |
275 // - MCC/MNC code of the cellular carrier if the device is connected to a | |
276 // cellular network, or | |
277 // - "Ethernet" in case the device is connected to ethernet. | |
278 // - An empty string in all other cases or if the network name is not | |
279 // exposed by platform APIs. | |
280 std::string id; | |
281 }; | |
282 | |
283 // Returns true if the cached network quality estimate was successfully read. | |
284 bool ReadCachedNetworkQualityEstimate(); | |
285 | |
286 // NetworkChangeNotifier::ConnectionTypeObserver implementation: | 247 // NetworkChangeNotifier::ConnectionTypeObserver implementation: |
287 void OnConnectionTypeChanged( | 248 void OnConnectionTypeChanged( |
288 NetworkChangeNotifier::ConnectionType type) override; | 249 NetworkChangeNotifier::ConnectionType type) override; |
289 | 250 |
290 // ExternalEstimateProvider::UpdatedEstimateObserver implementation. | 251 // ExternalEstimateProvider::UpdatedEstimateObserver implementation. |
291 void OnUpdatedEstimateAvailable(const base::TimeDelta& rtt, | 252 void OnUpdatedEstimateAvailable(const base::TimeDelta& rtt, |
292 int32_t downstream_throughput_kbps, | 253 int32_t downstream_throughput_kbps, |
293 int32_t upstream_throughput_kbps) override; | 254 int32_t upstream_throughput_kbps) override; |
294 | 255 |
295 // Returns true if the RTT is available and sets |rtt| to the RTT estimated at | 256 // Returns true if the RTT is available and sets |rtt| to the RTT estimated at |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
353 virtual double RandDouble() const; | 314 virtual double RandDouble() const; |
354 | 315 |
355 private: | 316 private: |
356 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations); | 317 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, StoreObservations); |
357 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation); | 318 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestAddObservation); |
358 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams); | 319 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ObtainOperatingParams); |
359 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | 320 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, |
360 ObtainAlgorithmToUseFromParams); | 321 ObtainAlgorithmToUseFromParams); |
361 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam); | 322 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, HalfLifeParam); |
362 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles); | 323 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, ComputedPercentiles); |
363 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestCaching); | |
364 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | |
365 TestLRUCacheMaximumSize); | |
366 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMetricsSince); | 324 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, TestGetMetricsSince); |
367 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, | 325 FRIEND_TEST_ALL_PREFIXES(NetworkQualityEstimatorTest, |
368 TestExternalEstimateProviderMergeEstimates); | 326 TestExternalEstimateProviderMergeEstimates); |
369 | 327 |
370 // Value of round trip time observations is in base::TimeDelta. | 328 // Value of round trip time observations is in base::TimeDelta. |
371 typedef nqe::internal::Observation<base::TimeDelta> RttObservation; | 329 typedef nqe::internal::Observation<base::TimeDelta> RttObservation; |
372 typedef nqe::internal::ObservationBuffer<base::TimeDelta> | 330 typedef nqe::internal::ObservationBuffer<base::TimeDelta> |
373 RttObservationBuffer; | 331 RttObservationBuffer; |
374 | 332 |
375 // Value of throughput observations is in kilobits per second. | 333 // Value of throughput observations is in kilobits per second. |
376 typedef nqe::internal::Observation<int32_t> ThroughputObservation; | 334 typedef nqe::internal::Observation<int32_t> ThroughputObservation; |
377 typedef nqe::internal::ObservationBuffer<int32_t> ThroughputObservationBuffer; | 335 typedef nqe::internal::ObservationBuffer<int32_t> ThroughputObservationBuffer; |
378 | 336 |
379 // This does not use a unordered_map or hash_map for code simplicity (key just | |
380 // implements operator<, rather than hash and equality) and because the map is | |
381 // tiny. | |
382 typedef std::map<NetworkID, nqe::internal::CachedNetworkQuality> | |
383 CachedNetworkQualities; | |
384 | |
385 // Algorithms supported by network quality estimator for computing effective | 337 // Algorithms supported by network quality estimator for computing effective |
386 // connection type. | 338 // connection type. |
387 enum class EffectiveConnectionTypeAlgorithm { | 339 enum class EffectiveConnectionTypeAlgorithm { |
388 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT = 0, | 340 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT = 0, |
389 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT, | 341 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT, |
390 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST | 342 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST |
391 }; | 343 }; |
392 | 344 |
393 // Defines how a metric (e.g, transport RTT) should be used when computing | 345 // Defines how a metric (e.g, transport RTT) should be used when computing |
394 // the effective connection type. | 346 // the effective connection type. |
(...skipping 22 matching lines...) Expand all Loading... |
417 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT; | 369 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT; |
418 | 370 |
419 // Minimum valid value of the variation parameter that holds RTT (in | 371 // Minimum valid value of the variation parameter that holds RTT (in |
420 // milliseconds) values. | 372 // milliseconds) values. |
421 static const int kMinimumRTTVariationParameterMsec = 1; | 373 static const int kMinimumRTTVariationParameterMsec = 1; |
422 | 374 |
423 // Minimum valid value of the variation parameter that holds throughput (in | 375 // Minimum valid value of the variation parameter that holds throughput (in |
424 // kilobits per second) values. | 376 // kilobits per second) values. |
425 static const int kMinimumThroughputVariationParameterKbps = 1; | 377 static const int kMinimumThroughputVariationParameterKbps = 1; |
426 | 378 |
427 // Maximum size of the cache that holds network quality estimates. | |
428 // Smaller size may reduce the cache hit rate due to frequent evictions. | |
429 // Larger size may affect performance. | |
430 static const size_t kMaximumNetworkQualityCacheSize = 10; | |
431 | |
432 // Returns the RTT value to be used when the valid RTT is unavailable. Readers | 379 // Returns the RTT value to be used when the valid RTT is unavailable. Readers |
433 // should discard RTT if it is set to the value returned by |InvalidRTT()|. | 380 // should discard RTT if it is set to the value returned by |InvalidRTT()|. |
434 static const base::TimeDelta InvalidRTT(); | 381 static const base::TimeDelta InvalidRTT(); |
435 | 382 |
436 // Records UMA when there is a change in connection type. | 383 // Records UMA when there is a change in connection type. |
437 void RecordMetricsOnConnectionTypeChanged() const; | 384 void RecordMetricsOnConnectionTypeChanged() const; |
438 | 385 |
439 // Records UMA on whether the NetworkID was available or not. Called right | 386 // Records UMA on whether the NetworkID was available or not. Called right |
440 // after a network change event. | 387 // after a network change event. |
441 void RecordNetworkIDAvailability() const; | 388 void RecordNetworkIDAvailability() const; |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
480 const std::vector<NetworkQualityObservationSource>& | 427 const std::vector<NetworkQualityObservationSource>& |
481 disallowed_observation_sources, | 428 disallowed_observation_sources, |
482 const base::TimeTicks& start_time, | 429 const base::TimeTicks& start_time, |
483 int percentile) const; | 430 int percentile) const; |
484 int32_t GetDownlinkThroughputKbpsEstimateInternal( | 431 int32_t GetDownlinkThroughputKbpsEstimateInternal( |
485 const base::TimeTicks& start_time, | 432 const base::TimeTicks& start_time, |
486 int percentile) const; | 433 int percentile) const; |
487 | 434 |
488 // Returns the current network ID checking by calling the platform APIs. | 435 // Returns the current network ID checking by calling the platform APIs. |
489 // Virtualized for testing. | 436 // Virtualized for testing. |
490 virtual NetworkID GetCurrentNetworkID() const; | 437 virtual nqe::internal::NetworkID GetCurrentNetworkID() const; |
491 | |
492 // Writes the estimated quality of the current network to the cache. | |
493 void CacheNetworkQualityEstimate(); | |
494 | 438 |
495 void NotifyObserversOfRTT(const RttObservation& observation); | 439 void NotifyObserversOfRTT(const RttObservation& observation); |
496 | 440 |
497 void NotifyObserversOfThroughput(const ThroughputObservation& observation); | 441 void NotifyObserversOfThroughput(const ThroughputObservation& observation); |
498 | 442 |
499 // Returns true only if the |request| can be used for RTT estimation. | 443 // Returns true only if the |request| can be used for RTT estimation. |
500 bool RequestProvidesRTTObservation(const URLRequest& request) const; | 444 bool RequestProvidesRTTObservation(const URLRequest& request) const; |
501 | 445 |
502 // Recomputes effective connection type, if it was computed more than the | 446 // Recomputes effective connection type, if it was computed more than the |
503 // specified duration ago, or if there has been a connection change recently. | 447 // specified duration ago, or if there has been a connection change recently. |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
539 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK, | 483 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK, |
540 EXTERNAL_ESTIMATE_PROVIDER_STATUS_RTT_AVAILABLE, | 484 EXTERNAL_ESTIMATE_PROVIDER_STATUS_RTT_AVAILABLE, |
541 EXTERNAL_ESTIMATE_PROVIDER_STATUS_DOWNLINK_BANDWIDTH_AVAILABLE, | 485 EXTERNAL_ESTIMATE_PROVIDER_STATUS_DOWNLINK_BANDWIDTH_AVAILABLE, |
542 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY | 486 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY |
543 }; | 487 }; |
544 | 488 |
545 // Records the metrics related to external estimate provider. | 489 // Records the metrics related to external estimate provider. |
546 void RecordExternalEstimateProviderMetrics( | 490 void RecordExternalEstimateProviderMetrics( |
547 NQEExternalEstimateProviderStatus status) const; | 491 NQEExternalEstimateProviderStatus status) const; |
548 | 492 |
| 493 // Returns true if the cached network quality estimate was successfully read. |
| 494 bool ReadCachedNetworkQualityEstimate(); |
| 495 |
549 // Records a correlation metric that can be used for computing the correlation | 496 // Records a correlation metric that can be used for computing the correlation |
550 // between HTTP-layer RTT, transport-layer RTT, throughput and the time | 497 // between HTTP-layer RTT, transport-layer RTT, throughput and the time |
551 // taken to complete |request|. | 498 // taken to complete |request|. |
552 void RecordCorrelationMetric(const URLRequest& request) const; | 499 void RecordCorrelationMetric(const URLRequest& request) const; |
553 | 500 |
554 // Returns true if transport RTT should be used for computing the effective | 501 // Returns true if transport RTT should be used for computing the effective |
555 // connection type. | 502 // connection type. |
556 bool UseTransportRTT() const; | 503 bool UseTransportRTT() const; |
557 | 504 |
558 // Determines if the requests to local host can be used in estimating the | 505 // Determines if the requests to local host can be used in estimating the |
(...skipping 25 matching lines...) Expand all Loading... |
584 base::TimeTicks last_effective_connection_type_computation_; | 531 base::TimeTicks last_effective_connection_type_computation_; |
585 | 532 |
586 // Intervals after the main frame request arrives at which accuracy of network | 533 // Intervals after the main frame request arrives at which accuracy of network |
587 // quality prediction is recorded. | 534 // quality prediction is recorded. |
588 std::vector<base::TimeDelta> accuracy_recording_intervals_; | 535 std::vector<base::TimeDelta> accuracy_recording_intervals_; |
589 | 536 |
590 // Time when last connection change was observed. | 537 // Time when last connection change was observed. |
591 base::TimeTicks last_connection_change_; | 538 base::TimeTicks last_connection_change_; |
592 | 539 |
593 // ID of the current network. | 540 // ID of the current network. |
594 NetworkID current_network_id_; | 541 nqe::internal::NetworkID current_network_id_; |
595 | 542 |
596 // Peak network quality (fastest round-trip-time (RTT) and highest | 543 // Peak network quality (fastest round-trip-time (RTT) and highest |
597 // downstream throughput) measured since last connectivity change. RTT is | 544 // downstream throughput) measured since last connectivity change. RTT is |
598 // measured from time the request is sent until the first byte received. | 545 // measured from time the request is sent until the first byte received. |
599 // The accuracy is decreased by ignoring these factors: | 546 // The accuracy is decreased by ignoring these factors: |
600 // 1) Multiple URLRequests can occur concurrently. | 547 // 1) Multiple URLRequests can occur concurrently. |
601 // 2) Includes server processing time. | 548 // 2) Includes server processing time. |
602 nqe::internal::NetworkQuality peak_network_quality_; | 549 nqe::internal::NetworkQuality peak_network_quality_; |
603 | 550 |
604 // Cache that stores quality of previously seen networks. | |
605 CachedNetworkQualities cached_network_qualities_; | |
606 | |
607 // Buffer that holds throughput observations (in kilobits per second) sorted | 551 // Buffer that holds throughput observations (in kilobits per second) sorted |
608 // by timestamp. | 552 // by timestamp. |
609 ThroughputObservationBuffer downstream_throughput_kbps_observations_; | 553 ThroughputObservationBuffer downstream_throughput_kbps_observations_; |
610 | 554 |
611 // Buffer that holds RTT observations sorted by timestamp. | 555 // Buffer that holds RTT observations sorted by timestamp. |
612 RttObservationBuffer rtt_observations_; | 556 RttObservationBuffer rtt_observations_; |
613 | 557 |
614 // Default network quality observations obtained from the network quality | 558 // Default network quality observations obtained from the network quality |
615 // estimator field trial parameters. The observations are indexed by | 559 // estimator field trial parameters. The observations are indexed by |
616 // ConnectionType. | 560 // ConnectionType. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
663 int32_t min_signal_strength_since_connection_change_; | 607 int32_t min_signal_strength_since_connection_change_; |
664 int32_t max_signal_strength_since_connection_change_; | 608 int32_t max_signal_strength_since_connection_change_; |
665 | 609 |
666 // It is costlier to add values to a sparse histogram. So, the correlation UMA | 610 // It is costlier to add values to a sparse histogram. So, the correlation UMA |
667 // is recorded with |correlation_uma_logging_probability_| since recording it | 611 // is recorded with |correlation_uma_logging_probability_| since recording it |
668 // in a sparse histogram for each request is unnecessary and cost-prohibitive. | 612 // in a sparse histogram for each request is unnecessary and cost-prohibitive. |
669 // e.g., if it is 0.0, then the UMA will never be recorded. On the other hand, | 613 // e.g., if it is 0.0, then the UMA will never be recorded. On the other hand, |
670 // if it is 1.0, then it will be recorded for all valid HTTP requests. | 614 // if it is 1.0, then it will be recorded for all valid HTTP requests. |
671 const double correlation_uma_logging_probability_; | 615 const double correlation_uma_logging_probability_; |
672 | 616 |
| 617 // Stores the qualities of different networks. |
| 618 nqe::internal::NetworkQualityStore network_quality_store_; |
| 619 |
673 base::ThreadChecker thread_checker_; | 620 base::ThreadChecker thread_checker_; |
674 | 621 |
675 base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_; | 622 base::WeakPtrFactory<NetworkQualityEstimator> weak_ptr_factory_; |
676 | 623 |
677 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator); | 624 DISALLOW_COPY_AND_ASSIGN(NetworkQualityEstimator); |
678 }; | 625 }; |
679 | 626 |
680 } // namespace net | 627 } // namespace net |
681 | 628 |
682 #endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ | 629 #endif // NET_NQE_NETWORK_QUALITY_ESTIMATOR_H_ |
OLD | NEW |