Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(69)

Side by Side Diff: net/base/network_quality_estimator.cc

Issue 1316863006: Populate EEP estimate in NQE (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Tests and mmenke comments Created 5 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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 static_assert(kMinRequestDurationMicroseconds > 0, 182 static_assert(kMinRequestDurationMicroseconds > 0,
183 "Minimum request duration must be > 0"); 183 "Minimum request duration must be > 0");
184 static_assert(kDefaultHalfLifeSeconds > 0, 184 static_assert(kDefaultHalfLifeSeconds > 0,
185 "Default half life duration must be > 0"); 185 "Default half life duration must be > 0");
186 static_assert(kMaximumNetworkQualityCacheSize > 0, 186 static_assert(kMaximumNetworkQualityCacheSize > 0,
187 "Size of the network quality cache must be > 0"); 187 "Size of the network quality cache must be > 0");
188 // This limit should not be increased unless the logic for removing the 188 // 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. 189 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue.
190 static_assert(kMaximumNetworkQualityCacheSize <= 10, 190 static_assert(kMaximumNetworkQualityCacheSize <= 10,
191 "Size of the network quality cache must <= 10"); 191 "Size of the network quality cache must <= 10");
192 192
193 ObtainOperatingParams(variation_params); 193 ObtainOperatingParams(variation_params);
194 NetworkChangeNotifier::AddConnectionTypeObserver(this); 194 NetworkChangeNotifier::AddConnectionTypeObserver(this);
195 if (external_estimates_provider_) 195 if (external_estimate_provider_) {
196 external_estimates_provider_->SetUpdatedEstimateDelegate(this); 196 RecordExternalEstimateProviderMetrics(
197 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE);
198 external_estimate_provider_->SetUpdatedEstimateDelegate(this);
199 QueryExternalEstimateProvider();
200 } else {
201 RecordExternalEstimateProviderMetrics(
202 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE);
203 }
197 current_network_id_ = GetCurrentNetworkID(); 204 current_network_id_ = GetCurrentNetworkID();
198 AddDefaultEstimates(); 205 AddDefaultEstimates();
199 } 206 }
200 207
201 // static 208 // static
202 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { 209 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() {
203 return base::TimeDelta::Max(); 210 return base::TimeDelta::Max();
204 } 211 }
205 212
206 void NetworkQualityEstimator::ObtainOperatingParams( 213 void NetworkQualityEstimator::ObtainOperatingParams(
207 const std::map<std::string, std::string>& variation_params) { 214 const std::map<std::string, std::string>& variation_params) {
208 DCHECK(thread_checker_.CalledOnValidThread()); 215 DCHECK(thread_checker_.CalledOnValidThread());
209 216
210 for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) { 217 for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) {
211 NetworkChangeNotifier::ConnectionType type = 218 NetworkChangeNotifier::ConnectionType type =
212 static_cast<NetworkChangeNotifier::ConnectionType>(i); 219 static_cast<NetworkChangeNotifier::ConnectionType>(i);
220 DCHECK_EQ(InvalidRTT(), default_observations_[i].rtt());
221 DCHECK_EQ(kInvalidThroughput,
222 default_observations_[i].downstream_throughput_kbps());
213 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; 223 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1;
214 // Name of the parameter that holds the RTT value for this connection type. 224 // Name of the parameter that holds the RTT value for this connection type.
215 std::string rtt_parameter_name = 225 std::string rtt_parameter_name =
216 std::string(GetNameForConnectionType(type)) 226 std::string(GetNameForConnectionType(type))
217 .append(kDefaultRTTMsecObservationSuffix); 227 .append(kDefaultRTTMsecObservationSuffix);
218 auto it = variation_params.find(rtt_parameter_name); 228 auto it = variation_params.find(rtt_parameter_name);
219 if (it != variation_params.end() && 229 if (it != variation_params.end() &&
220 base::StringToInt(it->second, &variations_value) && 230 base::StringToInt(it->second, &variations_value) &&
221 variations_value >= kMinimumRTTVariationParameterMsec) { 231 variations_value >= kMinimumRTTVariationParameterMsec) {
222 default_observations_[i] = 232 default_observations_[i] =
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 return request.url().is_valid() && 424 return request.url().is_valid() &&
413 (allow_localhost_requests_ || !IsLocalhost(request.url().host())) && 425 (allow_localhost_requests_ || !IsLocalhost(request.url().host())) &&
414 request.url().SchemeIsHTTPOrHTTPS() && 426 request.url().SchemeIsHTTPOrHTTPS() &&
415 // Verify that response headers are received, so it can be ensured that 427 // Verify that response headers are received, so it can be ensured that
416 // response is not cached. 428 // response is not cached.
417 !request.response_info().response_time.is_null() && 429 !request.response_info().response_time.is_null() &&
418 !request.was_cached() && 430 !request.was_cached() &&
419 request.creation_time() >= last_connection_change_; 431 request.creation_time() >= last_connection_change_;
420 } 432 }
421 433
434 void NetworkQualityEstimator::RecordExternalEstimateProviderMetrics(
435 NQEExternalEstimateProviderStatus status) const {
436 UMA_HISTOGRAM_ENUMERATION("NQE.ExternalEstimateProviderStatus", status,
437 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY);
438 }
439
422 void NetworkQualityEstimator::OnConnectionTypeChanged( 440 void NetworkQualityEstimator::OnConnectionTypeChanged(
423 NetworkChangeNotifier::ConnectionType type) { 441 NetworkChangeNotifier::ConnectionType type) {
424 DCHECK(thread_checker_.CalledOnValidThread()); 442 DCHECK(thread_checker_.CalledOnValidThread());
425 if (peak_network_quality_.rtt() != InvalidRTT()) { 443 if (peak_network_quality_.rtt() != InvalidRTT()) {
426 switch (current_network_id_.type) { 444 switch (current_network_id_.type) {
427 case NetworkChangeNotifier::CONNECTION_UNKNOWN: 445 case NetworkChangeNotifier::CONNECTION_UNKNOWN:
428 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown", 446 UMA_HISTOGRAM_TIMES("NQE.FastestRTT.Unknown",
429 peak_network_quality_.rtt()); 447 peak_network_quality_.rtt());
430 break; 448 break;
431 case NetworkChangeNotifier::CONNECTION_ETHERNET: 449 case NetworkChangeNotifier::CONNECTION_ETHERNET:
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
531 // Write the estimates of the previous network to the cache. 549 // Write the estimates of the previous network to the cache.
532 CacheNetworkQualityEstimate(); 550 CacheNetworkQualityEstimate();
533 551
534 // Clear the local state. 552 // Clear the local state.
535 last_connection_change_ = base::TimeTicks::Now(); 553 last_connection_change_ = base::TimeTicks::Now();
536 peak_network_quality_ = NetworkQuality(); 554 peak_network_quality_ = NetworkQuality();
537 downstream_throughput_kbps_observations_.Clear(); 555 downstream_throughput_kbps_observations_.Clear();
538 rtt_msec_observations_.Clear(); 556 rtt_msec_observations_.Clear();
539 current_network_id_ = GetCurrentNetworkID(); 557 current_network_id_ = GetCurrentNetworkID();
540 558
559 QueryExternalEstimateProvider();
560
541 // Read any cached estimates for the new network. If cached estimates are 561 // Read any cached estimates for the new network. If cached estimates are
542 // unavailable, add the default estimates. 562 // unavailable, add the default estimates.
543 if (!ReadCachedNetworkQualityEstimate()) 563 if (!ReadCachedNetworkQualityEstimate())
544 AddDefaultEstimates(); 564 AddDefaultEstimates();
545 estimated_median_network_quality_ = NetworkQuality(); 565 estimated_median_network_quality_ = NetworkQuality();
546 } 566 }
547 567
548 bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) const { 568 bool NetworkQualityEstimator::GetRTTEstimate(base::TimeDelta* rtt) {
549 DCHECK(thread_checker_.CalledOnValidThread()); 569 DCHECK(thread_checker_.CalledOnValidThread());
550 DCHECK(rtt); 570 DCHECK(rtt);
571 MaybeQueryExternalEstimateProvider();
551 if (rtt_msec_observations_.Size() == 0) { 572 if (rtt_msec_observations_.Size() == 0) {
552 *rtt = InvalidRTT(); 573 *rtt = InvalidRTT();
553 return false; 574 return false;
554 } 575 }
555 *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50); 576 *rtt = GetRTTEstimateInternal(base::TimeTicks(), 50);
556 return (*rtt != InvalidRTT()); 577 return (*rtt != InvalidRTT());
557 } 578 }
558 579
559 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate( 580 bool NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimate(int32_t* kbps) {
560 int32_t* kbps) const {
561 DCHECK(thread_checker_.CalledOnValidThread()); 581 DCHECK(thread_checker_.CalledOnValidThread());
562 DCHECK(kbps); 582 DCHECK(kbps);
583 MaybeQueryExternalEstimateProvider();
563 if (downstream_throughput_kbps_observations_.Size() == 0) { 584 if (downstream_throughput_kbps_observations_.Size() == 0) {
564 *kbps = kInvalidThroughput; 585 *kbps = kInvalidThroughput;
565 return false; 586 return false;
566 } 587 }
567 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50); 588 *kbps = GetDownlinkThroughputKbpsEstimateInternal(base::TimeTicks(), 50);
568 return (*kbps != kInvalidThroughput); 589 return (*kbps != kInvalidThroughput);
569 } 590 }
570 591
571 bool NetworkQualityEstimator::GetRecentMedianRTT( 592 bool NetworkQualityEstimator::GetRecentMedianRTT(
572 const base::TimeTicks& begin_timestamp, 593 const base::TimeTicks& begin_timestamp,
573 base::TimeDelta* rtt) const { 594 base::TimeDelta* rtt) {
574 DCHECK(thread_checker_.CalledOnValidThread()); 595 DCHECK(thread_checker_.CalledOnValidThread());
575 DCHECK(rtt); 596 DCHECK(rtt);
597
598 MaybeQueryExternalEstimateProvider();
576 *rtt = GetRTTEstimateInternal(begin_timestamp, 50); 599 *rtt = GetRTTEstimateInternal(begin_timestamp, 50);
577 return (*rtt != InvalidRTT()); 600 return (*rtt != InvalidRTT());
578 } 601 }
579 602
580 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( 603 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps(
581 const base::TimeTicks& begin_timestamp, 604 const base::TimeTicks& begin_timestamp,
582 int32_t* kbps) const { 605 int32_t* kbps) {
583 DCHECK(thread_checker_.CalledOnValidThread()); 606 DCHECK(thread_checker_.CalledOnValidThread());
584 DCHECK(kbps); 607 DCHECK(kbps);
608
609 MaybeQueryExternalEstimateProvider();
585 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); 610 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50);
586 return (*kbps != kInvalidThroughput); 611 return (*kbps != kInvalidThroughput);
587 } 612 }
588 613
589 NetworkQualityEstimator::Observation::Observation(int32_t value, 614 NetworkQualityEstimator::Observation::Observation(int32_t value,
590 base::TimeTicks timestamp) 615 base::TimeTicks timestamp)
591 : value(value), timestamp(timestamp) { 616 : value(value), timestamp(timestamp) {
592 DCHECK_GE(value, 0); 617 DCHECK_GE(value, 0);
593 DCHECK(!timestamp.is_null()); 618 DCHECK(!timestamp.is_null());
594 } 619 }
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
805 830
806 downstream_throughput_kbps_observations_.AddObservation(Observation( 831 downstream_throughput_kbps_observations_.AddObservation(Observation(
807 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now())); 832 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now()));
808 rtt_msec_observations_.AddObservation(Observation( 833 rtt_msec_observations_.AddObservation(Observation(
809 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now())); 834 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now()));
810 return true; 835 return true;
811 } 836 }
812 837
813 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { 838 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() {
814 DCHECK(thread_checker_.CalledOnValidThread()); 839 DCHECK(thread_checker_.CalledOnValidThread());
815 DCHECK(external_estimates_provider_); 840 DCHECK(external_estimate_provider_);
816 // TODO(tbansal): Query provider for the recent value. 841
842 RecordExternalEstimateProviderMetrics(
843 EXTERNAL_ESTIMATE_PROVIDER_STATUS_CALLBACK);
844 QueryExternalEstimateProvider();
845 }
846
847 void NetworkQualityEstimator::MaybeQueryExternalEstimateProvider() {
848 if (base::TimeTicks::Now() - external_estimate_request_time_ >=
849 base::TimeDelta::FromMilliseconds(
850 kExternalEstimateProviderQueryIntervalMsec)) {
mmenke 2015/09/14 20:07:06 None of the tests check this logic.
tbansal1 2015/09/14 23:46:56 Obsolete.
851 QueryExternalEstimateProvider();
852 }
853 }
854
855 void NetworkQualityEstimator::QueryExternalEstimateProvider() {
856 DCHECK(thread_checker_.CalledOnValidThread());
857
858 if (!external_estimate_provider_)
859 return;
860 RecordExternalEstimateProviderMetrics(
861 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERIED);
862 external_estimate_request_time_ = base::TimeTicks::Now();
863
864 base::TimeDelta time_since_last_update;
865
866 // Request a new estimate if estimate is not available, or if the available
867 // estimate is not fresh.
868 if (!external_estimate_provider_->GetTimeSinceLastUpdate(
869 &time_since_last_update) ||
870 time_since_last_update >
871 base::TimeDelta::FromMilliseconds(
872 kExternalEstimateProviderFreshnessDurationMsec)) {
873 // Request the external estimate provider for updated estimates. When the
874 // updates estimates are available, OnUpdatedEstimateAvailable() will be
875 // called.
876 external_estimate_provider_->RequestUpdate();
877 return;
878 }
879
880 RecordExternalEstimateProviderMetrics(
881 EXTERNAL_ESTIMATE_PROVIDER_STATUS_QUERY_SUCCESSFUL);
882 base::TimeDelta rtt;
883 if (external_estimate_provider_->GetRTT(&rtt)) {
884 rtt_msec_observations_.AddObservation(Observation(
885 rtt.InMilliseconds(), base::TimeTicks::Now() - time_since_last_update));
mmenke 2015/09/14 20:07:06 I still think just randomly adding these sources t
tbansal1 2015/09/14 23:46:56 Modified the CL to add estimate from external prov
886 }
887
888 int32_t downstream_throughput_kbps;
889 if (external_estimate_provider_->GetDownstreamThroughputKbps(
890 &downstream_throughput_kbps)) {
891 downstream_throughput_kbps_observations_.AddObservation(
892 Observation(downstream_throughput_kbps,
893 base::TimeTicks::Now() - time_since_last_update));
mmenke 2015/09/14 20:07:06 I don't think any of the tests check that these ob
tbansal1 2015/09/14 23:46:56 Added test to make sure that the observation size
894 }
817 } 895 }
818 896
819 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { 897 void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
820 DCHECK(thread_checker_.CalledOnValidThread()); 898 DCHECK(thread_checker_.CalledOnValidThread());
821 DCHECK_LE(cached_network_qualities_.size(), 899 DCHECK_LE(cached_network_qualities_.size(),
822 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); 900 static_cast<size_t>(kMaximumNetworkQualityCacheSize));
823 901
824 // If the network name is unavailable, caching should not be performed. 902 // If the network name is unavailable, caching should not be performed.
825 if (current_network_id_.id.empty()) 903 if (current_network_id_.id.empty())
826 return; 904 return;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
909 987
910 NetworkQualityEstimator::NetworkQuality& 988 NetworkQualityEstimator::NetworkQuality&
911 NetworkQualityEstimator::NetworkQuality:: 989 NetworkQualityEstimator::NetworkQuality::
912 operator=(const NetworkQuality& other) { 990 operator=(const NetworkQuality& other) {
913 rtt_ = other.rtt_; 991 rtt_ = other.rtt_;
914 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; 992 downstream_throughput_kbps_ = other.downstream_throughput_kbps_;
915 return *this; 993 return *this;
916 } 994 }
917 995
918 } // namespace net 996 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698