Chromium Code Reviews| 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 #include "net/base/network_quality_estimator.h" | 5 #include "net/base/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <float.h> | 7 #include <float.h> |
| 8 #include <algorithm> | 8 #include <algorithm> |
| 9 #include <cmath> | 9 #include <cmath> |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 171 bool allow_smaller_responses_for_tests) | 171 bool allow_smaller_responses_for_tests) |
| 172 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 172 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
| 173 allow_small_responses_(allow_smaller_responses_for_tests), | 173 allow_small_responses_(allow_smaller_responses_for_tests), |
| 174 last_connection_change_(base::TimeTicks::Now()), | 174 last_connection_change_(base::TimeTicks::Now()), |
| 175 current_network_id_( | 175 current_network_id_( |
| 176 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 176 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 177 std::string())), | 177 std::string())), |
| 178 downstream_throughput_kbps_observations_( | 178 downstream_throughput_kbps_observations_( |
| 179 GetWeightMultiplierPerSecond(variation_params)), | 179 GetWeightMultiplierPerSecond(variation_params)), |
| 180 rtt_msec_observations_(GetWeightMultiplierPerSecond(variation_params)), | 180 rtt_msec_observations_(GetWeightMultiplierPerSecond(variation_params)), |
| 181 external_estimates_provider_(external_estimates_provider.Pass()) { | 181 external_estimate_provider_(external_estimates_provider.Pass()), |
| 182 external_estimate_request_time_(base::TimeTicks()) { | |
| 182 static_assert(kMinRequestDurationMicroseconds > 0, | 183 static_assert(kMinRequestDurationMicroseconds > 0, |
| 183 "Minimum request duration must be > 0"); | 184 "Minimum request duration must be > 0"); |
| 184 static_assert(kDefaultHalfLifeSeconds > 0, | 185 static_assert(kDefaultHalfLifeSeconds > 0, |
| 185 "Default half life duration must be > 0"); | 186 "Default half life duration must be > 0"); |
| 186 static_assert(kMaximumNetworkQualityCacheSize > 0, | 187 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 187 "Size of the network quality cache must be > 0"); | 188 "Size of the network quality cache must be > 0"); |
| 188 // This limit should not be increased unless the logic for removing the | 189 // This limit should not be increased unless the logic for removing the |
| 189 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 190 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 190 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 191 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 191 "Size of the network quality cache must <= 10"); | 192 "Size of the network quality cache must <= 10"); |
| 192 | 193 |
| 193 ObtainOperatingParams(variation_params); | 194 ObtainOperatingParams(variation_params); |
| 194 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 195 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 195 if (external_estimates_provider_) | 196 if (external_estimate_provider_) { |
| 196 external_estimates_provider_->SetUpdatedEstimateDelegate(this); | 197 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", |
|
Alexei Svitkine (slow)
2015/09/08 21:33:10
Please make a helper function that logs this histo
tbansal1
2015/09/08 22:29:30
Made the helper function. Had to move the enum def
| |
| 198 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE, | |
| 199 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | |
| 200 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | |
| 201 QueryExternalEstimateProvider(); | |
| 202 } else { | |
| 203 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", | |
| 204 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE, | |
| 205 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | |
| 206 } | |
| 197 current_network_id_ = GetCurrentNetworkID(); | 207 current_network_id_ = GetCurrentNetworkID(); |
| 198 AddDefaultEstimates(); | 208 AddDefaultEstimates(); |
| 199 } | 209 } |
| 200 | 210 |
| 201 // static | 211 // static |
| 202 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { | 212 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { |
| 203 return base::TimeDelta::Max(); | 213 return base::TimeDelta::Max(); |
| 204 } | 214 } |
| 205 | 215 |
| 206 void NetworkQualityEstimator::ObtainOperatingParams( | 216 void NetworkQualityEstimator::ObtainOperatingParams( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 257 } | 267 } |
| 258 | 268 |
| 259 NetworkQualityEstimator::~NetworkQualityEstimator() { | 269 NetworkQualityEstimator::~NetworkQualityEstimator() { |
| 260 DCHECK(thread_checker_.CalledOnValidThread()); | 270 DCHECK(thread_checker_.CalledOnValidThread()); |
| 261 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 271 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| 262 } | 272 } |
| 263 | 273 |
| 264 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { | 274 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { |
| 265 DCHECK(thread_checker_.CalledOnValidThread()); | 275 DCHECK(thread_checker_.CalledOnValidThread()); |
| 266 | 276 |
| 277 MaybeQueryExternalEstimateProvider(); | |
| 267 if (!RequestProvidesUsefulObservations(request)) | 278 if (!RequestProvidesUsefulObservations(request)) |
| 268 return; | 279 return; |
| 269 | 280 |
| 270 // Update |estimated_median_network_quality_| if this is a main frame request. | 281 // Update |estimated_median_network_quality_| if this is a main frame request. |
| 271 if (request.load_flags() & LOAD_MAIN_FRAME) { | 282 if (request.load_flags() & LOAD_MAIN_FRAME) { |
| 272 estimated_median_network_quality_ = NetworkQuality( | 283 estimated_median_network_quality_ = NetworkQuality( |
| 273 GetRTTEstimateInternal(base::TimeTicks(), 50), | 284 GetRTTEstimateInternal(base::TimeTicks(), 50), |
| 274 GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50)); | 285 GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50)); |
| 275 } | 286 } |
| 276 | 287 |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 307 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { | 318 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { |
| 308 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), | 319 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), |
| 309 observed_rtt.InMilliseconds()); | 320 observed_rtt.InMilliseconds()); |
| 310 } | 321 } |
| 311 } | 322 } |
| 312 | 323 |
| 313 void NetworkQualityEstimator::NotifyRequestCompleted( | 324 void NetworkQualityEstimator::NotifyRequestCompleted( |
| 314 const URLRequest& request) { | 325 const URLRequest& request) { |
| 315 DCHECK(thread_checker_.CalledOnValidThread()); | 326 DCHECK(thread_checker_.CalledOnValidThread()); |
| 316 | 327 |
| 328 MaybeQueryExternalEstimateProvider(); | |
| 317 if (!RequestProvidesUsefulObservations(request)) | 329 if (!RequestProvidesUsefulObservations(request)) |
| 318 return; | 330 return; |
| 319 | 331 |
| 320 base::TimeTicks now = base::TimeTicks::Now(); | 332 base::TimeTicks now = base::TimeTicks::Now(); |
| 321 LoadTimingInfo load_timing_info; | 333 LoadTimingInfo load_timing_info; |
| 322 request.GetLoadTimingInfo(&load_timing_info); | 334 request.GetLoadTimingInfo(&load_timing_info); |
| 323 | 335 |
| 324 // If the load timing info is unavailable, it probably means that the request | 336 // If the load timing info is unavailable, it probably means that the request |
| 325 // did not go over the network. | 337 // did not go over the network. |
| 326 if (load_timing_info.send_start.is_null() || | 338 if (load_timing_info.send_start.is_null() || |
| (...skipping 204 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 531 // Write the estimates of the previous network to the cache. | 543 // Write the estimates of the previous network to the cache. |
| 532 CacheNetworkQualityEstimate(); | 544 CacheNetworkQualityEstimate(); |
| 533 | 545 |
| 534 // Clear the local state. | 546 // Clear the local state. |
| 535 last_connection_change_ = base::TimeTicks::Now(); | 547 last_connection_change_ = base::TimeTicks::Now(); |
| 536 peak_network_quality_ = NetworkQuality(); | 548 peak_network_quality_ = NetworkQuality(); |
| 537 downstream_throughput_kbps_observations_.Clear(); | 549 downstream_throughput_kbps_observations_.Clear(); |
| 538 rtt_msec_observations_.Clear(); | 550 rtt_msec_observations_.Clear(); |
| 539 current_network_id_ = GetCurrentNetworkID(); | 551 current_network_id_ = GetCurrentNetworkID(); |
| 540 | 552 |
| 553 QueryExternalEstimateProvider(); | |
| 554 | |
| 541 // Read any cached estimates for the new network. If cached estimates are | 555 // Read any cached estimates for the new network. If cached estimates are |
| 542 // unavailable, add the default estimates. | 556 // unavailable, add the default estimates. |
| 543 if (!ReadCachedNetworkQualityEstimate()) | 557 if (!ReadCachedNetworkQualityEstimate()) |
| 544 AddDefaultEstimates(); | 558 AddDefaultEstimates(); |
| 545 estimated_median_network_quality_ = NetworkQuality(); | 559 estimated_median_network_quality_ = NetworkQuality(); |
| 546 } | 560 } |
| 547 | 561 |
| 548 bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) const { | 562 bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) { |
| 549 DCHECK(thread_checker_.CalledOnValidThread()); | 563 DCHECK(thread_checker_.CalledOnValidThread()); |
| 550 DCHECK(rtt); | 564 DCHECK(rtt); |
| 565 MaybeQueryExternalEstimateProvider(); | |
| 551 if (rtt_msec_observations_.Size() == 0) { | 566 if (rtt_msec_observations_.Size() == 0) { |
| 552 *rtt = InvalidRTT(); | 567 *rtt = InvalidRTT(); |
| 553 return false; | 568 return false; |
| 554 } | 569 } |
| 555 *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50); | 570 *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50); |
| 556 return (*rtt != InvalidRTT()); | 571 return (*rtt != InvalidRTT()); |
| 557 } | 572 } |
| 558 | 573 |
| 559 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate( | 574 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(int32_t* kbps) { |
| 560 int32_t* kbps) const { | |
| 561 DCHECK(thread_checker_.CalledOnValidThread()); | 575 DCHECK(thread_checker_.CalledOnValidThread()); |
| 562 DCHECK(kbps); | 576 DCHECK(kbps); |
| 577 MaybeQueryExternalEstimateProvider(); | |
| 563 if (downstream_throughput_kbps_observations_.Size() == 0) { | 578 if (downstream_throughput_kbps_observations_.Size() == 0) { |
| 564 *kbps = kInvalidThroughput; | 579 *kbps = kInvalidThroughput; |
| 565 return false; | 580 return false; |
| 566 } | 581 } |
| 567 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); | 582 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); |
| 568 return (*kbps != kInvalidThroughput); | 583 return (*kbps != kInvalidThroughput); |
| 569 } | 584 } |
| 570 | 585 |
| 571 bool NetworkQualityEstimator::GetRecentMedianRTT( | 586 bool NetworkQualityEstimator::GetRecentMedianRTT( |
| 572 const base::TimeTicks& begin_timestamp, | 587 const base::TimeTicks& begin_timestamp, |
| 573 base::TimeDelta* rtt) const { | 588 base::TimeDelta* rtt) { |
| 574 DCHECK(thread_checker_.CalledOnValidThread()); | 589 DCHECK(thread_checker_.CalledOnValidThread()); |
| 575 DCHECK(rtt); | 590 DCHECK(rtt); |
| 591 | |
| 592 MaybeQueryExternalEstimateProvider(); | |
| 576 *rtt = GetRTTEstimateInternal(begin_timestamp, 50); | 593 *rtt = GetRTTEstimateInternal(begin_timestamp, 50); |
| 577 return (*rtt != InvalidRTT()); | 594 return (*rtt != InvalidRTT()); |
| 578 } | 595 } |
| 579 | 596 |
| 580 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( | 597 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( |
| 581 const base::TimeTicks& begin_timestamp, | 598 const base::TimeTicks& begin_timestamp, |
| 582 int32_t* kbps) const { | 599 int32_t* kbps) { |
| 583 DCHECK(thread_checker_.CalledOnValidThread()); | 600 DCHECK(thread_checker_.CalledOnValidThread()); |
| 584 DCHECK(kbps); | 601 DCHECK(kbps); |
| 602 | |
| 603 MaybeQueryExternalEstimateProvider(); | |
| 585 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); | 604 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); |
| 586 return (*kbps != kInvalidThroughput); | 605 return (*kbps != kInvalidThroughput); |
| 587 } | 606 } |
| 588 | 607 |
| 589 NetworkQualityEstimator::Observation::Observation(int32_t value, | 608 NetworkQualityEstimator::Observation::Observation(int32_t value, |
| 590 base::TimeTicks timestamp) | 609 base::TimeTicks timestamp) |
| 591 : value(value), timestamp(timestamp) { | 610 : value(value), timestamp(timestamp) { |
| 592 DCHECK_GE(value, 0); | 611 DCHECK_GE(value, 0); |
| 593 DCHECK(!timestamp.is_null()); | 612 DCHECK(!timestamp.is_null()); |
| 594 } | 613 } |
| (...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 805 | 824 |
| 806 downstream_throughput_kbps_observations_.AddObservation(Observation( | 825 downstream_throughput_kbps_observations_.AddObservation(Observation( |
| 807 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now())); | 826 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now())); |
| 808 rtt_msec_observations_.AddObservation(Observation( | 827 rtt_msec_observations_.AddObservation(Observation( |
| 809 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now())); | 828 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now())); |
| 810 return true; | 829 return true; |
| 811 } | 830 } |
| 812 | 831 |
| 813 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { | 832 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { |
| 814 DCHECK(thread_checker_.CalledOnValidThread()); | 833 DCHECK(thread_checker_.CalledOnValidThread()); |
| 815 DCHECK(external_estimates_provider_); | 834 DCHECK(external_estimate_provider_); |
| 816 // TODO(tbansal): Query provider for the recent value. | 835 |
| 836 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", | |
| 837 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK, | |
| 838 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | |
| 839 | |
| 840 QueryExternalEstimateProvider(); | |
| 841 } | |
| 842 | |
| 843 void NetworkQualityEstimator::MaybeQueryExternalEstimateProvider() { | |
| 844 if (base::TimeTicks::Now() - external_estimate_request_time_ >= | |
| 845 base::TimeDelta::FromMilliseconds( | |
| 846 kExternalEstimateProviderQueryIntervalMsec)) { | |
| 847 QueryExternalEstimateProvider(); | |
| 848 } | |
| 849 } | |
| 850 | |
| 851 void NetworkQualityEstimator::QueryExternalEstimateProvider() { | |
| 852 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 853 | |
| 854 if (!external_estimate_provider_) | |
| 855 return; | |
| 856 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", | |
| 857 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED, | |
| 858 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | |
| 859 | |
| 860 external_estimate_request_time_ = base::TimeTicks::Now(); | |
| 861 | |
| 862 base::TimeDelta time_since_last_update; | |
| 863 if (!external_estimate_provider_->GetTimeSinceLastUpdate( | |
| 864 &time_since_last_update) || | |
| 865 time_since_last_update > | |
| 866 base::TimeDelta::FromMilliseconds( | |
| 867 kExternalEstimateProviderQueryIntervalMsec)) { | |
| 868 // Request the external estimate provider for updated estimates. When the | |
| 869 // updates estimates are available, OnUpdatedEstimateAvailable() will get | |
| 870 // called. | |
| 871 external_estimate_provider_->RequestUpdate(); | |
| 872 return; | |
| 873 } | |
| 874 | |
| 875 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", | |
| 876 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL, | |
| 877 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | |
| 878 | |
| 879 base::TimeDelta rtt; | |
| 880 if (external_estimate_provider_->GetRTT(&rtt)) { | |
| 881 rtt_msec_observations_.AddObservation(Observation( | |
| 882 rtt.InMilliseconds(), base::TimeTicks::Now() - time_since_last_update)); | |
| 883 } | |
| 884 | |
| 885 int32_t downstream_throughput_kbps; | |
| 886 if (external_estimate_provider_->GetDownstreamThroughputKbps( | |
| 887 &downstream_throughput_kbps)) { | |
| 888 downstream_throughput_kbps_observations_.AddObservation( | |
| 889 Observation(downstream_throughput_kbps, | |
| 890 base::TimeTicks::Now() - time_since_last_update)); | |
| 891 } | |
| 817 } | 892 } |
| 818 | 893 |
| 819 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { | 894 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { |
| 820 DCHECK(thread_checker_.CalledOnValidThread()); | 895 DCHECK(thread_checker_.CalledOnValidThread()); |
| 821 DCHECK_LE(cached_network_qualities_.size(), | 896 DCHECK_LE(cached_network_qualities_.size(), |
| 822 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 897 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 823 | 898 |
| 824 // If the network name is unavailable, caching should not be performed. | 899 // If the network name is unavailable, caching should not be performed. |
| 825 if (current_network_id_.id.empty()) | 900 if (current_network_id_.id.empty()) |
| 826 return; | 901 return; |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 909 | 984 |
| 910 NetworkQualityEstimator::NetworkQuality& | 985 NetworkQualityEstimator::NetworkQuality& |
| 911 NetworkQualityEstimator::NetworkQuality:: | 986 NetworkQualityEstimator::NetworkQuality:: |
| 912 operator=(const NetworkQuality& other) { | 987 operator=(const NetworkQuality& other) { |
| 913 rtt_ = other.rtt_; | 988 rtt_ = other.rtt_; |
| 914 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | 989 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; |
| 915 return *this; | 990 return *this; |
| 916 } | 991 } |
| 917 | 992 |
| 918 } // namespace net | 993 } // namespace net |
| OLD | NEW |