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()) { | |
mmenke
2015/09/11 14:26:29
Don't need to explicitly call the default construc
tbansal1
2015/09/11 21:24:30
Done.
| |
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 RecordExternalEstimateProviderMetrics( |
198 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); | |
199 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | |
200 QueryExternalEstimateProvider(); | |
201 } else { | |
202 RecordExternalEstimateProviderMetrics( | |
203 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); | |
204 } | |
197 current_network_id_ = GetCurrentNetworkID(); | 205 current_network_id_ = GetCurrentNetworkID(); |
198 AddDefaultEstimates(); | 206 AddDefaultEstimates(); |
199 } | 207 } |
200 | 208 |
201 // static | 209 // static |
202 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { | 210 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { |
203 return base::TimeDelta::Max(); | 211 return base::TimeDelta::Max(); |
204 } | 212 } |
205 | 213 |
206 void NetworkQualityEstimator::ObtainOperatingParams( | 214 void NetworkQualityEstimator::ObtainOperatingParams( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
257 } | 265 } |
258 | 266 |
259 NetworkQualityEstimator::~NetworkQualityEstimator() { | 267 NetworkQualityEstimator::~NetworkQualityEstimator() { |
260 DCHECK(thread_checker_.CalledOnValidThread()); | 268 DCHECK(thread_checker_.CalledOnValidThread()); |
261 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 269 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
262 } | 270 } |
263 | 271 |
264 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { | 272 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { |
265 DCHECK(thread_checker_.CalledOnValidThread()); | 273 DCHECK(thread_checker_.CalledOnValidThread()); |
266 | 274 |
275 MaybeQueryExternalEstimateProvider(); | |
267 if (!RequestProvidesUsefulObservations(request)) | 276 if (!RequestProvidesUsefulObservations(request)) |
268 return; | 277 return; |
269 | 278 |
270 // Update |estimated_median_network_quality_| if this is a main frame request. | 279 // Update |estimated_median_network_quality_| if this is a main frame request. |
271 if (request.load_flags() & LOAD_MAIN_FRAME) { | 280 if (request.load_flags() & LOAD_MAIN_FRAME) { |
272 estimated_median_network_quality_ = NetworkQuality( | 281 estimated_median_network_quality_ = NetworkQuality( |
273 GetRTTEstimateInternal(base::TimeTicks(), 50), | 282 GetRTTEstimateInternal(base::TimeTicks(), 50), |
274 GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50)); | 283 GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50)); |
275 } | 284 } |
276 | 285 |
(...skipping 30 matching lines...) Expand all Loading... | |
307 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { | 316 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { |
308 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), | 317 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), |
309 observed_rtt.InMilliseconds()); | 318 observed_rtt.InMilliseconds()); |
310 } | 319 } |
311 } | 320 } |
312 | 321 |
313 void NetworkQualityEstimator::NotifyRequestCompleted( | 322 void NetworkQualityEstimator::NotifyRequestCompleted( |
314 const URLRequest& request) { | 323 const URLRequest& request) { |
315 DCHECK(thread_checker_.CalledOnValidThread()); | 324 DCHECK(thread_checker_.CalledOnValidThread()); |
316 | 325 |
326 MaybeQueryExternalEstimateProvider(); | |
317 if (!RequestProvidesUsefulObservations(request)) | 327 if (!RequestProvidesUsefulObservations(request)) |
318 return; | 328 return; |
319 | 329 |
320 base::TimeTicks now = base::TimeTicks::Now(); | 330 base::TimeTicks now = base::TimeTicks::Now(); |
321 LoadTimingInfo load_timing_info; | 331 LoadTimingInfo load_timing_info; |
322 request.GetLoadTimingInfo(&load_timing_info); | 332 request.GetLoadTimingInfo(&load_timing_info); |
323 | 333 |
324 // If the load timing info is unavailable, it probably means that the request | 334 // If the load timing info is unavailable, it probably means that the request |
325 // did not go over the network. | 335 // did not go over the network. |
326 if (load_timing_info.send_start.is_null() || | 336 if (load_timing_info.send_start.is_null() || |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
412 return request.url().is_valid() && | 422 return request.url().is_valid() && |
413 (allow_localhost_requests_ || !IsLocalhost(request.url().host())) && | 423 (allow_localhost_requests_ || !IsLocalhost(request.url().host())) && |
414 request.url().SchemeIsHTTPOrHTTPS() && | 424 request.url().SchemeIsHTTPOrHTTPS() && |
415 // Verify that response headers are received, so it can be ensured that | 425 // Verify that response headers are received, so it can be ensured that |
416 // response is not cached. | 426 // response is not cached. |
417 !request.response_info().response_time.is_null() && | 427 !request.response_info().response_time.is_null() && |
418 !request.was_cached() && | 428 !request.was_cached() && |
419 request.creation_time() >= last_connection_change_; | 429 request.creation_time() >= last_connection_change_; |
420 } | 430 } |
421 | 431 |
432 void NetworkQualityEstimator::RecordExternalEstimateProviderMetrics( | |
433 NQEExternalEstimateProviderStatus status) const { | |
434 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", status, | |
435 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); | |
436 } | |
437 | |
422 void NetworkQualityEstimator::OnConnectionTypeChanged( | 438 void NetworkQualityEstimator::OnConnectionTypeChanged( |
423 NetworkChangeNotifier::ConnectionType type) { | 439 NetworkChangeNotifier::ConnectionType type) { |
424 DCHECK(thread_checker_.CalledOnValidThread()); | 440 DCHECK(thread_checker_.CalledOnValidThread()); |
425 if (peak_network_quality_.rtt() != InvalidRTT()) { | 441 if (peak_network_quality_.rtt() != InvalidRTT()) { |
426 switch (current_network_id_.type) { | 442 switch (current_network_id_.type) { |
427 case NetworkChangeNotifier::CONNECTION_UNKNOWN: | 443 case NetworkChangeNotifier::CONNECTION_UNKNOWN: |
428 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", | 444 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", |
429 peak_network_quality_.rtt()); | 445 peak_network_quality_.rtt()); |
430 break; | 446 break; |
431 case NetworkChangeNotifier::CONNECTION_ETHERNET: | 447 case NetworkChangeNotifier::CONNECTION_ETHERNET: |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
531 // Write the estimates of the previous network to the cache. | 547 // Write the estimates of the previous network to the cache. |
532 CacheNetworkQualityEstimate(); | 548 CacheNetworkQualityEstimate(); |
533 | 549 |
534 // Clear the local state. | 550 // Clear the local state. |
535 last_connection_change_ = base::TimeTicks::Now(); | 551 last_connection_change_ = base::TimeTicks::Now(); |
536 peak_network_quality_ = NetworkQuality(); | 552 peak_network_quality_ = NetworkQuality(); |
537 downstream_throughput_kbps_observations_.Clear(); | 553 downstream_throughput_kbps_observations_.Clear(); |
538 rtt_msec_observations_.Clear(); | 554 rtt_msec_observations_.Clear(); |
539 current_network_id_ = GetCurrentNetworkID(); | 555 current_network_id_ = GetCurrentNetworkID(); |
540 | 556 |
557 QueryExternalEstimateProvider(); | |
558 | |
541 // Read any cached estimates for the new network. If cached estimates are | 559 // Read any cached estimates for the new network. If cached estimates are |
542 // unavailable, add the default estimates. | 560 // unavailable, add the default estimates. |
543 if (!ReadCachedNetworkQualityEstimate()) | 561 if (!ReadCachedNetworkQualityEstimate()) |
544 AddDefaultEstimates(); | 562 AddDefaultEstimates(); |
545 estimated_median_network_quality_ = NetworkQuality(); | 563 estimated_median_network_quality_ = NetworkQuality(); |
546 } | 564 } |
547 | 565 |
548 bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) const { | 566 bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) { |
549 DCHECK(thread_checker_.CalledOnValidThread()); | 567 DCHECK(thread_checker_.CalledOnValidThread()); |
550 DCHECK(rtt); | 568 DCHECK(rtt); |
569 MaybeQueryExternalEstimateProvider(); | |
mmenke
2015/09/11 15:07:22
Wait..So the frequency one calls this method can a
mmenke
2015/09/11 15:17:52
Ah, right...It's the queries vs maybe queries.
Th
tbansal1
2015/09/11 21:24:30
Please see the reply below.
| |
551 if (rtt_msec_observations_.Size() == 0) { | 570 if (rtt_msec_observations_.Size() == 0) { |
552 *rtt = InvalidRTT(); | 571 *rtt = InvalidRTT(); |
553 return false; | 572 return false; |
554 } | 573 } |
555 *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50); | 574 *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50); |
556 return (*rtt != InvalidRTT()); | 575 return (*rtt != InvalidRTT()); |
557 } | 576 } |
558 | 577 |
559 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate( | 578 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(int32_t* kbps) { |
560 int32_t* kbps) const { | |
561 DCHECK(thread_checker_.CalledOnValidThread()); | 579 DCHECK(thread_checker_.CalledOnValidThread()); |
562 DCHECK(kbps); | 580 DCHECK(kbps); |
581 MaybeQueryExternalEstimateProvider(); | |
563 if (downstream_throughput_kbps_observations_.Size() == 0) { | 582 if (downstream_throughput_kbps_observations_.Size() == 0) { |
564 *kbps = kInvalidThroughput; | 583 *kbps = kInvalidThroughput; |
565 return false; | 584 return false; |
566 } | 585 } |
567 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); | 586 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); |
568 return (*kbps != kInvalidThroughput); | 587 return (*kbps != kInvalidThroughput); |
569 } | 588 } |
570 | 589 |
571 bool NetworkQualityEstimator::GetRecentMedianRTT( | 590 bool NetworkQualityEstimator::GetRecentMedianRTT( |
572 const base::TimeTicks& begin_timestamp, | 591 const base::TimeTicks& begin_timestamp, |
573 base::TimeDelta* rtt) const { | 592 base::TimeDelta* rtt) { |
574 DCHECK(thread_checker_.CalledOnValidThread()); | 593 DCHECK(thread_checker_.CalledOnValidThread()); |
575 DCHECK(rtt); | 594 DCHECK(rtt); |
595 | |
596 MaybeQueryExternalEstimateProvider(); | |
576 *rtt = GetRTTEstimateInternal(begin_timestamp, 50); | 597 *rtt = GetRTTEstimateInternal(begin_timestamp, 50); |
577 return (*rtt != InvalidRTT()); | 598 return (*rtt != InvalidRTT()); |
578 } | 599 } |
579 | 600 |
580 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( | 601 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( |
581 const base::TimeTicks& begin_timestamp, | 602 const base::TimeTicks& begin_timestamp, |
582 int32_t* kbps) const { | 603 int32_t* kbps) { |
583 DCHECK(thread_checker_.CalledOnValidThread()); | 604 DCHECK(thread_checker_.CalledOnValidThread()); |
584 DCHECK(kbps); | 605 DCHECK(kbps); |
606 | |
607 MaybeQueryExternalEstimateProvider(); | |
585 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); | 608 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); |
586 return (*kbps != kInvalidThroughput); | 609 return (*kbps != kInvalidThroughput); |
587 } | 610 } |
588 | 611 |
589 NetworkQualityEstimator::Observation::Observation(int32_t value, | 612 NetworkQualityEstimator::Observation::Observation(int32_t value, |
590 base::TimeTicks timestamp) | 613 base::TimeTicks timestamp) |
591 : value(value), timestamp(timestamp) { | 614 : value(value), timestamp(timestamp) { |
592 DCHECK_GE(value, 0); | 615 DCHECK_GE(value, 0); |
593 DCHECK(!timestamp.is_null()); | 616 DCHECK(!timestamp.is_null()); |
594 } | 617 } |
(...skipping 208 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
803 DCHECK_NE(InvalidRTT(), network_quality.rtt()); | 826 DCHECK_NE(InvalidRTT(), network_quality.rtt()); |
804 DCHECK_NE(kInvalidThroughput, network_quality.downstream_throughput_kbps()); | 827 DCHECK_NE(kInvalidThroughput, network_quality.downstream_throughput_kbps()); |
805 | 828 |
806 downstream_throughput_kbps_observations_.AddObservation(Observation( | 829 downstream_throughput_kbps_observations_.AddObservation(Observation( |
807 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now())); | 830 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now())); |
808 rtt_msec_observations_.AddObservation(Observation( | 831 rtt_msec_observations_.AddObservation(Observation( |
809 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now())); | 832 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now())); |
810 return true; | 833 return true; |
811 } | 834 } |
812 | 835 |
813 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { | 836 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { |
mmenke
2015/09/11 15:07:22
Why is this needed? Seems like we pull it wheneve
tbansal1
2015/09/11 21:24:31
EEP that we are currently using on Android has asy
| |
814 DCHECK(thread_checker_.CalledOnValidThread()); | 837 DCHECK(thread_checker_.CalledOnValidThread()); |
815 DCHECK(external_estimates_provider_); | 838 DCHECK(external_estimate_provider_); |
816 // TODO(tbansal): Query provider for the recent value. | 839 |
840 RecordExternalEstimateProviderMetrics( | |
841 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK); | |
842 QueryExternalEstimateProvider(); | |
843 } | |
844 | |
845 void NetworkQualityEstimator::MaybeQueryExternalEstimateProvider() { | |
846 if (base::TimeTicks::Now() - external_estimate_request_time_ >= | |
847 base::TimeDelta::FromMilliseconds( | |
848 kExternalEstimateProviderQueryIntervalMsec)) { | |
849 QueryExternalEstimateProvider(); | |
850 } | |
851 } | |
852 | |
853 void NetworkQualityEstimator::QueryExternalEstimateProvider() { | |
854 DCHECK(thread_checker_.CalledOnValidThread()); | |
855 | |
856 if (!external_estimate_provider_) | |
857 return; | |
858 RecordExternalEstimateProviderMetrics( | |
859 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED); | |
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)) { | |
mmenke
2015/09/11 14:26:29
Why do both MaybeQueryExternalEstimateProvider and
tbansal1
2015/09/11 21:24:31
One is checking when was the last time native requ
| |
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 RecordExternalEstimateProviderMetrics( | |
876 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL); | |
877 base::TimeDelta rtt; | |
878 if (external_estimate_provider_->GetRTT(&rtt)) { | |
879 rtt_msec_observations_.AddObservation(Observation( | |
880 rtt.InMilliseconds(), base::TimeTicks::Now() - time_since_last_update)); | |
mmenke
2015/09/11 14:26:29
So we just toss in the EEP's estimates in a bucket
tbansal1
2015/09/11 21:24:31
Long-term goal is to look at other useful events:
| |
881 } | |
882 | |
883 int32_t downstream_throughput_kbps; | |
884 if (external_estimate_provider_->GetDownstreamThroughputKbps( | |
885 &downstream_throughput_kbps)) { | |
886 downstream_throughput_kbps_observations_.AddObservation( | |
887 Observation(downstream_throughput_kbps, | |
888 base::TimeTicks::Now() - time_since_last_update)); | |
889 } | |
817 } | 890 } |
818 | 891 |
819 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { | 892 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { |
820 DCHECK(thread_checker_.CalledOnValidThread()); | 893 DCHECK(thread_checker_.CalledOnValidThread()); |
821 DCHECK_LE(cached_network_qualities_.size(), | 894 DCHECK_LE(cached_network_qualities_.size(), |
822 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 895 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
823 | 896 |
824 // If the network name is unavailable, caching should not be performed. | 897 // If the network name is unavailable, caching should not be performed. |
825 if (current_network_id_.id.empty()) | 898 if (current_network_id_.id.empty()) |
826 return; | 899 return; |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
909 | 982 |
910 NetworkQualityEstimator::NetworkQuality& | 983 NetworkQualityEstimator::NetworkQuality& |
911 NetworkQualityEstimator::NetworkQuality:: | 984 NetworkQualityEstimator::NetworkQuality:: |
912 operator=(const NetworkQuality& other) { | 985 operator=(const NetworkQuality& other) { |
913 rtt_ = other.rtt_; | 986 rtt_ = other.rtt_; |
914 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | 987 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; |
915 return *this; | 988 return *this; |
916 } | 989 } |
917 | 990 |
918 } // namespace net | 991 } // namespace net |
OLD | NEW |