| 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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 133 bool allow_smaller_responses_for_tests) | 133 bool allow_smaller_responses_for_tests) |
| 134 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 134 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
| 135 allow_small_responses_(allow_smaller_responses_for_tests), | 135 allow_small_responses_(allow_smaller_responses_for_tests), |
| 136 last_connection_change_(base::TimeTicks::Now()), | 136 last_connection_change_(base::TimeTicks::Now()), |
| 137 current_network_id_( | 137 current_network_id_( |
| 138 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 138 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 139 std::string())), | 139 std::string())), |
| 140 downstream_throughput_kbps_observations_( | 140 downstream_throughput_kbps_observations_( |
| 141 GetWeightMultiplierPerSecond(variation_params)), | 141 GetWeightMultiplierPerSecond(variation_params)), |
| 142 rtt_msec_observations_(GetWeightMultiplierPerSecond(variation_params)), | 142 rtt_msec_observations_(GetWeightMultiplierPerSecond(variation_params)), |
| 143 external_estimates_provider_(external_estimates_provider.Pass()) { | 143 external_estimates_provider_(external_estimates_provider.Pass()), |
| 144 rtt_observer_list_(new base::ObserverListThreadSafe<RTTObserver>()), |
| 145 throughput_observer_list_( |
| 146 new base::ObserverListThreadSafe<ThroughputObserver>()) { |
| 144 static_assert(kMinRequestDurationMicroseconds > 0, | 147 static_assert(kMinRequestDurationMicroseconds > 0, |
| 145 "Minimum request duration must be > 0"); | 148 "Minimum request duration must be > 0"); |
| 146 static_assert(kDefaultHalfLifeSeconds > 0, | 149 static_assert(kDefaultHalfLifeSeconds > 0, |
| 147 "Default half life duration must be > 0"); | 150 "Default half life duration must be > 0"); |
| 148 static_assert(kMaximumNetworkQualityCacheSize > 0, | 151 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 149 "Size of the network quality cache must be > 0"); | 152 "Size of the network quality cache must be > 0"); |
| 150 // This limit should not be increased unless the logic for removing the | 153 // This limit should not be increased unless the logic for removing the |
| 151 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 154 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 152 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 155 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 153 "Size of the network quality cache must <= 10"); | 156 "Size of the network quality cache must <= 10"); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 198 variations_value >= kMinimumThroughputVariationParameterKbps) { | 201 variations_value >= kMinimumThroughputVariationParameterKbps) { |
| 199 default_observations_[i] = | 202 default_observations_[i] = |
| 200 NetworkQuality(default_observations_[i].rtt(), variations_value); | 203 NetworkQuality(default_observations_[i].rtt(), variations_value); |
| 201 } | 204 } |
| 202 } | 205 } |
| 203 } | 206 } |
| 204 | 207 |
| 205 void NetworkQualityEstimator::AddDefaultEstimates() { | 208 void NetworkQualityEstimator::AddDefaultEstimates() { |
| 206 DCHECK(thread_checker_.CalledOnValidThread()); | 209 DCHECK(thread_checker_.CalledOnValidThread()); |
| 207 if (default_observations_[current_network_id_.type].rtt() != InvalidRTT()) { | 210 if (default_observations_[current_network_id_.type].rtt() != InvalidRTT()) { |
| 208 rtt_msec_observations_.AddObservation(Observation( | 211 Observation rtt_observation( |
| 209 default_observations_[current_network_id_.type].rtt().InMilliseconds(), | 212 default_observations_[current_network_id_.type].rtt().InMilliseconds(), |
| 210 base::TimeTicks::Now())); | 213 base::TimeTicks::Now(), OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); |
| 214 rtt_msec_observations_.AddObservation(rtt_observation); |
| 215 NotifyObserversOfRTT(rtt_observation); |
| 211 } | 216 } |
| 212 if (default_observations_[current_network_id_.type] | 217 if (default_observations_[current_network_id_.type] |
| 213 .downstream_throughput_kbps() != kInvalidThroughput) { | 218 .downstream_throughput_kbps() != kInvalidThroughput) { |
| 219 Observation throughput_observation( |
| 220 default_observations_[current_network_id_.type] |
| 221 .downstream_throughput_kbps(), |
| 222 base::TimeTicks::Now(), OBSERVATION_SOURCE_DEFAULT_FROM_PLATFORM); |
| 214 downstream_throughput_kbps_observations_.AddObservation( | 223 downstream_throughput_kbps_observations_.AddObservation( |
| 215 Observation(default_observations_[current_network_id_.type] | 224 throughput_observation); |
| 216 .downstream_throughput_kbps(), | 225 NotifyObserversOfThroughput(throughput_observation); |
| 217 base::TimeTicks::Now())); | |
| 218 } | 226 } |
| 219 } | 227 } |
| 220 | 228 |
| 221 NetworkQualityEstimator::~NetworkQualityEstimator() { | 229 NetworkQualityEstimator::~NetworkQualityEstimator() { |
| 222 DCHECK(thread_checker_.CalledOnValidThread()); | 230 DCHECK(thread_checker_.CalledOnValidThread()); |
| 223 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 231 NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| 232 rtt_observer_list_->AssertEmpty(); |
| 233 throughput_observer_list_->AssertEmpty(); |
| 224 } | 234 } |
| 225 | 235 |
| 226 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { | 236 void NetworkQualityEstimator::NotifyHeadersReceived(const URLRequest& request) { |
| 227 DCHECK(thread_checker_.CalledOnValidThread()); | 237 DCHECK(thread_checker_.CalledOnValidThread()); |
| 228 | 238 |
| 229 if (!RequestProvidesUsefulObservations(request)) | 239 if (!RequestProvidesUsefulObservations(request)) |
| 230 return; | 240 return; |
| 231 | 241 |
| 232 // Update |estimated_median_network_quality_| if this is a main frame request. | 242 // Update |estimated_median_network_quality_| if this is a main frame request. |
| 233 if (request.load_flags() & LOAD_MAIN_FRAME) { | 243 if (request.load_flags() & LOAD_MAIN_FRAME) { |
| (...skipping 21 matching lines...) Expand all Loading... |
| 255 | 265 |
| 256 // Duration between when the resource was requested and when response | 266 // Duration between when the resource was requested and when response |
| 257 // headers were received. | 267 // headers were received. |
| 258 base::TimeDelta observed_rtt = headers_received_time - request_start_time; | 268 base::TimeDelta observed_rtt = headers_received_time - request_start_time; |
| 259 DCHECK_GE(observed_rtt, base::TimeDelta()); | 269 DCHECK_GE(observed_rtt, base::TimeDelta()); |
| 260 if (observed_rtt < peak_network_quality_.rtt()) { | 270 if (observed_rtt < peak_network_quality_.rtt()) { |
| 261 peak_network_quality_ = NetworkQuality( | 271 peak_network_quality_ = NetworkQuality( |
| 262 observed_rtt, peak_network_quality_.downstream_throughput_kbps()); | 272 observed_rtt, peak_network_quality_.downstream_throughput_kbps()); |
| 263 } | 273 } |
| 264 | 274 |
| 265 rtt_msec_observations_.AddObservation( | 275 Observation rtt_observation(observed_rtt.InMilliseconds(), now, |
| 266 Observation(observed_rtt.InMilliseconds(), now)); | 276 OBSERVATION_SOURCE_URL_REQUEST); |
| 277 rtt_msec_observations_.AddObservation(rtt_observation); |
| 278 NotifyObserversOfRTT(rtt_observation); |
| 267 | 279 |
| 268 // Compare the RTT observation with the estimated value and record it. | 280 // Compare the RTT observation with the estimated value and record it. |
| 269 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { | 281 if (estimated_median_network_quality_.rtt() != InvalidRTT()) { |
| 270 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), | 282 RecordRTTUMA(estimated_median_network_quality_.rtt().InMilliseconds(), |
| 271 observed_rtt.InMilliseconds()); | 283 observed_rtt.InMilliseconds()); |
| 272 } | 284 } |
| 273 } | 285 } |
| 274 | 286 |
| 275 void NetworkQualityEstimator::NotifyRequestCompleted( | 287 void NetworkQualityEstimator::NotifyRequestCompleted( |
| 276 const URLRequest& request) { | 288 const URLRequest& request) { |
| (...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 323 // connection. | 335 // connection. |
| 324 if (downstream_kbps - downstream_kbps_as_integer > 0) | 336 if (downstream_kbps - downstream_kbps_as_integer > 0) |
| 325 downstream_kbps_as_integer++; | 337 downstream_kbps_as_integer++; |
| 326 | 338 |
| 327 DCHECK_GT(downstream_kbps_as_integer, 0.0); | 339 DCHECK_GT(downstream_kbps_as_integer, 0.0); |
| 328 if (downstream_kbps_as_integer > | 340 if (downstream_kbps_as_integer > |
| 329 peak_network_quality_.downstream_throughput_kbps()) | 341 peak_network_quality_.downstream_throughput_kbps()) |
| 330 peak_network_quality_ = | 342 peak_network_quality_ = |
| 331 NetworkQuality(peak_network_quality_.rtt(), downstream_kbps_as_integer); | 343 NetworkQuality(peak_network_quality_.rtt(), downstream_kbps_as_integer); |
| 332 | 344 |
| 345 Observation throughput_observation(downstream_kbps_as_integer, now, |
| 346 OBSERVATION_SOURCE_URL_REQUEST); |
| 333 downstream_throughput_kbps_observations_.AddObservation( | 347 downstream_throughput_kbps_observations_.AddObservation( |
| 334 Observation(downstream_kbps_as_integer, now)); | 348 throughput_observation); |
| 349 NotifyObserversOfThroughput(throughput_observation); |
| 350 } |
| 351 |
| 352 void NetworkQualityEstimator::AddRTTObserver(RTTObserver* rtt_observer) { |
| 353 rtt_observer_list_->AddObserver(rtt_observer); |
| 354 } |
| 355 |
| 356 void NetworkQualityEstimator::RemoveRTTObserver(RTTObserver* rtt_observer) { |
| 357 rtt_observer_list_->RemoveObserver(rtt_observer); |
| 358 } |
| 359 |
| 360 void NetworkQualityEstimator::AddThroughputObserver( |
| 361 ThroughputObserver* throughput_observer) { |
| 362 throughput_observer_list_->AddObserver(throughput_observer); |
| 363 } |
| 364 |
| 365 void NetworkQualityEstimator::RemoveThroughputObserver( |
| 366 ThroughputObserver* throughput_observer) { |
| 367 throughput_observer_list_->RemoveObserver(throughput_observer); |
| 368 } |
| 369 |
| 370 void NetworkQualityEstimator::Configure(bool allow_local_host_requests, |
| 371 bool allow_smaller_responses) { |
| 372 allow_localhost_requests_ = allow_local_host_requests, |
| 373 allow_small_responses_ = allow_smaller_responses; |
| 335 } | 374 } |
| 336 | 375 |
| 337 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, | 376 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, |
| 338 int32_t actual_value_msec) const { | 377 int32_t actual_value_msec) const { |
| 339 DCHECK(thread_checker_.CalledOnValidThread()); | 378 DCHECK(thread_checker_.CalledOnValidThread()); |
| 340 | 379 |
| 341 // Record the difference between the actual and the estimated value. | 380 // Record the difference between the actual and the estimated value. |
| 342 if (estimated_value_msec >= actual_value_msec) { | 381 if (estimated_value_msec >= actual_value_msec) { |
| 343 base::HistogramBase* difference_rtt = | 382 base::HistogramBase* difference_rtt = |
| 344 GetHistogram("DifferenceRTTEstimatedAndActual.", | 383 GetHistogram("DifferenceRTTEstimatedAndActual.", |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( | 581 bool NetworkQualityEstimator::GetRecentMedianDownlinkThroughputKbps( |
| 543 const base::TimeTicks& begin_timestamp, | 582 const base::TimeTicks& begin_timestamp, |
| 544 int32_t* kbps) const { | 583 int32_t* kbps) const { |
| 545 DCHECK(thread_checker_.CalledOnValidThread()); | 584 DCHECK(thread_checker_.CalledOnValidThread()); |
| 546 DCHECK(kbps); | 585 DCHECK(kbps); |
| 547 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); | 586 *kbps = GetDownlinkThroughputKbpsEstimateInternal(begin_timestamp, 50); |
| 548 return (*kbps != kInvalidThroughput); | 587 return (*kbps != kInvalidThroughput); |
| 549 } | 588 } |
| 550 | 589 |
| 551 NetworkQualityEstimator::Observation::Observation(int32_t value, | 590 NetworkQualityEstimator::Observation::Observation(int32_t value, |
| 552 base::TimeTicks timestamp) | 591 base::TimeTicks timestamp, |
| 553 : value(value), timestamp(timestamp) { | 592 ObservationSource source) |
| 593 : value(value), timestamp(timestamp), source(source) { |
| 554 DCHECK_GE(value, 0); | 594 DCHECK_GE(value, 0); |
| 555 DCHECK(!timestamp.is_null()); | 595 DCHECK(!timestamp.is_null()); |
| 556 } | 596 } |
| 557 | 597 |
| 558 NetworkQualityEstimator::Observation::~Observation() { | 598 NetworkQualityEstimator::Observation::~Observation() { |
| 559 } | 599 } |
| 560 | 600 |
| 561 NetworkQualityEstimator::ObservationBuffer::ObservationBuffer( | 601 NetworkQualityEstimator::ObservationBuffer::ObservationBuffer( |
| 562 double weight_multiplier_per_second) | 602 double weight_multiplier_per_second) |
| 563 : weight_multiplier_per_second_(weight_multiplier_per_second) { | 603 : weight_multiplier_per_second_(weight_multiplier_per_second) { |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 758 cached_network_qualities_.find(current_network_id_); | 798 cached_network_qualities_.find(current_network_id_); |
| 759 | 799 |
| 760 if (it == cached_network_qualities_.end()) | 800 if (it == cached_network_qualities_.end()) |
| 761 return false; | 801 return false; |
| 762 | 802 |
| 763 NetworkQuality network_quality(it->second.network_quality()); | 803 NetworkQuality network_quality(it->second.network_quality()); |
| 764 | 804 |
| 765 DCHECK_NE(InvalidRTT(), network_quality.rtt()); | 805 DCHECK_NE(InvalidRTT(), network_quality.rtt()); |
| 766 DCHECK_NE(kInvalidThroughput, network_quality.downstream_throughput_kbps()); | 806 DCHECK_NE(kInvalidThroughput, network_quality.downstream_throughput_kbps()); |
| 767 | 807 |
| 768 downstream_throughput_kbps_observations_.AddObservation(Observation( | 808 Observation througphput_observation( |
| 769 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now())); | 809 network_quality.downstream_throughput_kbps(), base::TimeTicks::Now(), |
| 770 rtt_msec_observations_.AddObservation(Observation( | 810 OBSERVATION_SOURCE_CACHED_ESTIMATE); |
| 771 network_quality.rtt().InMilliseconds(), base::TimeTicks::Now())); | 811 downstream_throughput_kbps_observations_.AddObservation( |
| 812 througphput_observation); |
| 813 NotifyObserversOfThroughput(througphput_observation); |
| 814 |
| 815 Observation rtt_observation(network_quality.rtt().InMilliseconds(), |
| 816 base::TimeTicks::Now(), |
| 817 OBSERVATION_SOURCE_CACHED_ESTIMATE); |
| 818 rtt_msec_observations_.AddObservation(rtt_observation); |
| 819 NotifyObserversOfRTT(rtt_observation); |
| 820 |
| 772 return true; | 821 return true; |
| 773 } | 822 } |
| 774 | 823 |
| 775 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { | 824 void NetworkQualityEstimator::OnUpdatedEstimateAvailable() { |
| 776 DCHECK(thread_checker_.CalledOnValidThread()); | 825 DCHECK(thread_checker_.CalledOnValidThread()); |
| 777 DCHECK(external_estimates_provider_); | 826 DCHECK(external_estimates_provider_); |
| 778 // TODO(tbansal): Query provider for the recent value. | 827 // TODO(tbansal): Query provider for the recent value. |
| 779 } | 828 } |
| 780 | 829 |
| 781 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { | 830 void NetworkQualityEstimator::CacheNetworkQualityEstimate() { |
| (...skipping 28 matching lines...) Expand all Loading... |
| 810 } | 859 } |
| 811 DCHECK_LT(cached_network_qualities_.size(), | 860 DCHECK_LT(cached_network_qualities_.size(), |
| 812 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 861 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 813 | 862 |
| 814 cached_network_qualities_.insert(std::make_pair( | 863 cached_network_qualities_.insert(std::make_pair( |
| 815 current_network_id_, CachedNetworkQuality(network_quality))); | 864 current_network_id_, CachedNetworkQuality(network_quality))); |
| 816 DCHECK_LE(cached_network_qualities_.size(), | 865 DCHECK_LE(cached_network_qualities_.size(), |
| 817 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 866 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 818 } | 867 } |
| 819 | 868 |
| 869 void NetworkQualityEstimator::NotifyObserversOfRTT( |
| 870 const Observation& observation) { |
| 871 rtt_observer_list_->Notify(FROM_HERE, &RTTObserver::OnRTTObservation, |
| 872 observation.value, observation.timestamp, |
| 873 observation.source); |
| 874 } |
| 875 |
| 876 void NetworkQualityEstimator::NotifyObserversOfThroughput( |
| 877 const Observation& observation) { |
| 878 throughput_observer_list_->Notify( |
| 879 FROM_HERE, &ThroughputObserver::OnThroughputObservation, |
| 880 observation.value, observation.timestamp, observation.source); |
| 881 } |
| 882 |
| 820 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | 883 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( |
| 821 const NetworkQuality& network_quality) | 884 const NetworkQuality& network_quality) |
| 822 : last_update_time_(base::TimeTicks::Now()), | 885 : last_update_time_(base::TimeTicks::Now()), |
| 823 network_quality_(network_quality) { | 886 network_quality_(network_quality) { |
| 824 } | 887 } |
| 825 | 888 |
| 826 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | 889 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( |
| 827 const CachedNetworkQuality& other) | 890 const CachedNetworkQuality& other) |
| 828 : last_update_time_(other.last_update_time_), | 891 : last_update_time_(other.last_update_time_), |
| 829 network_quality_(other.network_quality_) { | 892 network_quality_(other.network_quality_) { |
| (...skipping 27 matching lines...) Expand all Loading... |
| 857 | 920 |
| 858 NetworkQualityEstimator::NetworkQuality& | 921 NetworkQualityEstimator::NetworkQuality& |
| 859 NetworkQualityEstimator::NetworkQuality:: | 922 NetworkQualityEstimator::NetworkQuality:: |
| 860 operator=(const NetworkQuality& other) { | 923 operator=(const NetworkQuality& other) { |
| 861 rtt_ = other.rtt_; | 924 rtt_ = other.rtt_; |
| 862 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | 925 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; |
| 863 return *this; | 926 return *this; |
| 864 } | 927 } |
| 865 | 928 |
| 866 } // namespace net | 929 } // namespace net |
| OLD | NEW |