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> |
| 11 #include <utility> | 11 #include <utility> |
| 12 #include <vector> | 12 #include <vector> |
| 13 | 13 |
| 14 #include "base/logging.h" | 14 #include "base/logging.h" |
| 15 #include "base/metrics/histogram.h" | 15 #include "base/metrics/histogram.h" |
| 16 #include "base/metrics/histogram_base.h" | 16 #include "base/metrics/histogram_base.h" |
| 17 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
| 18 #include "base/thread_task_runner_handle.h" | |
| 18 #include "build/build_config.h" | 19 #include "build/build_config.h" |
| 19 #include "net/base/load_flags.h" | 20 #include "net/base/load_flags.h" |
| 20 #include "net/base/load_timing_info.h" | 21 #include "net/base/load_timing_info.h" |
| 21 #include "net/base/network_interfaces.h" | 22 #include "net/base/network_interfaces.h" |
| 23 #include "net/base/socket_performance_watcher.h" | |
| 22 #include "net/base/url_util.h" | 24 #include "net/base/url_util.h" |
| 23 #include "net/url_request/url_request.h" | 25 #include "net/url_request/url_request.h" |
| 24 #include "url/gurl.h" | 26 #include "url/gurl.h" |
| 25 | 27 |
| 26 #if defined(OS_ANDROID) | 28 #if defined(OS_ANDROID) |
| 27 #include "net/android/network_library.h" | 29 #include "net/android/network_library.h" |
| 28 #endif // OS_ANDROID | 30 #endif // OS_ANDROID |
| 29 | 31 |
| 30 namespace { | 32 namespace { |
| 31 | 33 |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 110 const char prefix[] = "NQE."; | 112 const char prefix[] = "NQE."; |
| 111 return base::Histogram::FactoryGet( | 113 return base::Histogram::FactoryGet( |
| 112 prefix + statistic_name + GetNameForConnectionType(type), kLowerLimit, | 114 prefix + statistic_name + GetNameForConnectionType(type), kLowerLimit, |
| 113 max_limit, kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag); | 115 max_limit, kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 114 } | 116 } |
| 115 | 117 |
| 116 } // namespace | 118 } // namespace |
| 117 | 119 |
| 118 namespace net { | 120 namespace net { |
| 119 | 121 |
| 122 // SocketWatcher implements SocketPerformanceWatcher, and notifies | |
| 123 // NetworkQualityEstimator of various socket performance events. SocketWatcher | |
| 124 // is not thread-safe. | |
| 125 class NetworkQualityEstimator::SocketWatcher : public SocketPerformanceWatcher { | |
|
bengr
2016/04/07 00:20:05
Any chance I could convince you to move this to an
Ryan Sleevi
2016/04/07 00:27:53
I specifically asked for this. I don't feel you ca
tbansal1
2016/04/07 01:43:36
Acknowledged.
| |
| 126 public: | |
| 127 SocketWatcher( | |
| 128 SocketPerformanceWatcherFactory::Protocol protocol, | |
|
Ryan Sleevi
2016/04/04 22:34:04
DESIGN NOTE (Future): As/if you change SocketPerfo
tbansal1
2016/04/04 23:46:32
OK, I will write down a quick design note to see w
| |
| 129 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 130 const base::WeakPtr<NetworkQualityEstimator>& network_quality_estimator) | |
| 131 : protocol_(protocol), | |
| 132 task_runner_(std::move(task_runner)), | |
| 133 network_quality_estimator_(network_quality_estimator) {} | |
| 134 | |
| 135 ~SocketWatcher() override {} | |
| 136 | |
| 137 // SocketPerformanceWatcher implementation: | |
| 138 void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override { | |
| 139 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 140 | |
| 141 task_runner_->PostTask( | |
| 142 FROM_HERE, base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable, | |
| 143 network_quality_estimator_, protocol_, rtt)); | |
| 144 } | |
| 145 | |
| 146 bool ShouldNotifyUpdatedRTT() const override { | |
| 147 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 148 | |
| 149 return true; | |
| 150 } | |
| 151 | |
| 152 void Reset() override { DCHECK(thread_checker_.CalledOnValidThread()); } | |
| 153 | |
| 154 private: | |
| 155 // Transport layer protocol used by the socket that |this| is watching. | |
| 156 const SocketPerformanceWatcherFactory::Protocol protocol_; | |
|
bengr
2016/04/07 00:20:05
I agree with Ryan's design note above.
tbansal1
2016/04/07 01:43:36
I believe the eventual decision was to keep 1 fact
| |
| 157 | |
| 158 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 159 | |
| 160 base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_; | |
| 161 | |
| 162 base::ThreadChecker thread_checker_; | |
| 163 | |
| 164 DISALLOW_COPY_AND_ASSIGN(SocketWatcher); | |
| 165 }; | |
| 166 | |
| 167 // SocketWatcherFactory implements SocketPerformanceWatcherFactory, and is | |
| 168 // owned by NetworkQualityEstimator. SocketWatcherFactory is thread safe. | |
| 169 class NetworkQualityEstimator::SocketWatcherFactory | |
| 170 : public SocketPerformanceWatcherFactory { | |
| 171 public: | |
| 172 SocketWatcherFactory( | |
| 173 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
| 174 const base::WeakPtr<NetworkQualityEstimator>& network_quality_estimator) | |
| 175 : task_runner_(std::move(task_runner)), | |
| 176 network_quality_estimator_(network_quality_estimator) {} | |
| 177 | |
| 178 ~SocketWatcherFactory() override {} | |
| 179 | |
| 180 // SocketPerformanceWatcherFactory implementation: | |
| 181 scoped_ptr<SocketPerformanceWatcher> CreateSocketPerformanceWatcher( | |
| 182 const Protocol protocol) override { | |
| 183 return scoped_ptr<SocketPerformanceWatcher>( | |
| 184 new SocketWatcher(protocol, task_runner_, network_quality_estimator_)); | |
| 185 } | |
| 186 | |
| 187 private: | |
| 188 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
| 189 | |
| 190 base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_; | |
| 191 | |
| 192 DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory); | |
| 193 }; | |
| 194 | |
| 120 const int32_t NetworkQualityEstimator::kInvalidThroughput = 0; | 195 const int32_t NetworkQualityEstimator::kInvalidThroughput = 0; |
| 121 | 196 |
| 122 NetworkQualityEstimator::NetworkQualityEstimator( | 197 NetworkQualityEstimator::NetworkQualityEstimator( |
| 123 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, | 198 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, |
| 124 const std::map<std::string, std::string>& variation_params) | 199 const std::map<std::string, std::string>& variation_params) |
| 125 : NetworkQualityEstimator(std::move(external_estimates_provider), | 200 : NetworkQualityEstimator(std::move(external_estimates_provider), |
| 126 variation_params, | 201 variation_params, |
| 127 false, | 202 false, |
| 128 false) {} | 203 false) {} |
| 129 | 204 |
| 130 NetworkQualityEstimator::NetworkQualityEstimator( | 205 NetworkQualityEstimator::NetworkQualityEstimator( |
| 131 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, | 206 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, |
| 132 const std::map<std::string, std::string>& variation_params, | 207 const std::map<std::string, std::string>& variation_params, |
| 133 bool allow_local_host_requests_for_tests, | 208 bool allow_local_host_requests_for_tests, |
| 134 bool allow_smaller_responses_for_tests) | 209 bool allow_smaller_responses_for_tests) |
| 135 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 210 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
| 136 allow_small_responses_(allow_smaller_responses_for_tests), | 211 allow_small_responses_(allow_smaller_responses_for_tests), |
| 137 last_connection_change_(base::TimeTicks::Now()), | 212 last_connection_change_(base::TimeTicks::Now()), |
| 138 current_network_id_( | 213 current_network_id_( |
| 139 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 214 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 140 std::string())), | 215 std::string())), |
| 141 downstream_throughput_kbps_observations_( | 216 downstream_throughput_kbps_observations_( |
| 142 GetWeightMultiplierPerSecond(variation_params)), | 217 GetWeightMultiplierPerSecond(variation_params)), |
| 143 rtt_observations_(GetWeightMultiplierPerSecond(variation_params)), | 218 rtt_observations_(GetWeightMultiplierPerSecond(variation_params)), |
| 144 external_estimate_provider_(std::move(external_estimates_provider)) { | 219 external_estimate_provider_(std::move(external_estimates_provider)), |
| 220 weak_ptr_factory_(this) { | |
| 145 static_assert(kMinRequestDurationMicroseconds > 0, | 221 static_assert(kMinRequestDurationMicroseconds > 0, |
| 146 "Minimum request duration must be > 0"); | 222 "Minimum request duration must be > 0"); |
| 147 static_assert(kDefaultHalfLifeSeconds > 0, | 223 static_assert(kDefaultHalfLifeSeconds > 0, |
| 148 "Default half life duration must be > 0"); | 224 "Default half life duration must be > 0"); |
| 149 static_assert(kMaximumNetworkQualityCacheSize > 0, | 225 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 150 "Size of the network quality cache must be > 0"); | 226 "Size of the network quality cache must be > 0"); |
| 151 // This limit should not be increased unless the logic for removing the | 227 // This limit should not be increased unless the logic for removing the |
| 152 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 228 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 153 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 229 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 154 "Size of the network quality cache must <= 10"); | 230 "Size of the network quality cache must <= 10"); |
| 155 | 231 |
| 156 ObtainOperatingParams(variation_params); | 232 ObtainOperatingParams(variation_params); |
| 157 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 233 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 158 if (external_estimate_provider_) { | 234 if (external_estimate_provider_) { |
| 159 RecordExternalEstimateProviderMetrics( | 235 RecordExternalEstimateProviderMetrics( |
| 160 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); | 236 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); |
| 161 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | 237 external_estimate_provider_->SetUpdatedEstimateDelegate(this); |
| 162 QueryExternalEstimateProvider(); | 238 QueryExternalEstimateProvider(); |
| 163 } else { | 239 } else { |
| 164 RecordExternalEstimateProviderMetrics( | 240 RecordExternalEstimateProviderMetrics( |
| 165 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); | 241 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); |
| 166 } | 242 } |
| 167 current_network_id_ = GetCurrentNetworkID(); | 243 current_network_id_ = GetCurrentNetworkID(); |
| 168 AddDefaultEstimates(); | 244 AddDefaultEstimates(); |
| 245 | |
| 246 watcher_factory_.reset(new SocketWatcherFactory( | |
| 247 base::ThreadTaskRunnerHandle::Get(), weak_ptr_factory_.GetWeakPtr())); | |
| 169 } | 248 } |
| 170 | 249 |
| 171 // static | 250 // static |
| 172 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { | 251 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { |
| 173 return base::TimeDelta::Max(); | 252 return base::TimeDelta::Max(); |
| 174 } | 253 } |
| 175 | 254 |
| 176 void NetworkQualityEstimator::ObtainOperatingParams( | 255 void NetworkQualityEstimator::ObtainOperatingParams( |
| 177 const std::map<std::string, std::string>& variation_params) { | 256 const std::map<std::string, std::string>& variation_params) { |
| 178 DCHECK(thread_checker_.CalledOnValidThread()); | 257 DCHECK(thread_checker_.CalledOnValidThread()); |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 369 DCHECK(thread_checker_.CalledOnValidThread()); | 448 DCHECK(thread_checker_.CalledOnValidThread()); |
| 370 throughput_observer_list_.AddObserver(throughput_observer); | 449 throughput_observer_list_.AddObserver(throughput_observer); |
| 371 } | 450 } |
| 372 | 451 |
| 373 void NetworkQualityEstimator::RemoveThroughputObserver( | 452 void NetworkQualityEstimator::RemoveThroughputObserver( |
| 374 ThroughputObserver* throughput_observer) { | 453 ThroughputObserver* throughput_observer) { |
| 375 DCHECK(thread_checker_.CalledOnValidThread()); | 454 DCHECK(thread_checker_.CalledOnValidThread()); |
| 376 throughput_observer_list_.RemoveObserver(throughput_observer); | 455 throughput_observer_list_.RemoveObserver(throughput_observer); |
| 377 } | 456 } |
| 378 | 457 |
| 458 SocketPerformanceWatcherFactory* | |
| 459 NetworkQualityEstimator::GetSocketPerformanceWatcherFactory() { | |
| 460 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 461 | |
| 462 return watcher_factory_.get(); | |
| 463 } | |
| 464 | |
| 379 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, | 465 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, |
| 380 int32_t actual_value_msec) const { | 466 int32_t actual_value_msec) const { |
| 381 DCHECK(thread_checker_.CalledOnValidThread()); | 467 DCHECK(thread_checker_.CalledOnValidThread()); |
| 382 | 468 |
| 383 // Record the difference between the actual and the estimated value. | 469 // Record the difference between the actual and the estimated value. |
| 384 if (estimated_value_msec >= actual_value_msec) { | 470 if (estimated_value_msec >= actual_value_msec) { |
| 385 base::HistogramBase* difference_rtt = | 471 base::HistogramBase* difference_rtt = |
| 386 GetHistogram("DifferenceRTTEstimatedAndActual.", | 472 GetHistogram("DifferenceRTTEstimatedAndActual.", |
| 387 current_network_id_.type, 10 * 1000); // 10 seconds | 473 current_network_id_.type, 10 * 1000); // 10 seconds |
| 388 difference_rtt->Add(estimated_value_msec - actual_value_msec); | 474 difference_rtt->Add(estimated_value_msec - actual_value_msec); |
| (...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 897 } | 983 } |
| 898 DCHECK_LT(cached_network_qualities_.size(), | 984 DCHECK_LT(cached_network_qualities_.size(), |
| 899 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 985 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 900 | 986 |
| 901 cached_network_qualities_.insert(std::make_pair( | 987 cached_network_qualities_.insert(std::make_pair( |
| 902 current_network_id_, CachedNetworkQuality(network_quality))); | 988 current_network_id_, CachedNetworkQuality(network_quality))); |
| 903 DCHECK_LE(cached_network_qualities_.size(), | 989 DCHECK_LE(cached_network_qualities_.size(), |
| 904 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 990 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
| 905 } | 991 } |
| 906 | 992 |
| 907 scoped_ptr<SocketPerformanceWatcher> | |
| 908 NetworkQualityEstimator::CreateSocketPerformanceWatcher( | |
| 909 const Protocol protocol) { | |
| 910 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 911 | |
| 912 return scoped_ptr<SocketPerformanceWatcher>( | |
| 913 new SocketPerformanceWatcher(protocol, this)); | |
| 914 } | |
| 915 | |
| 916 void NetworkQualityEstimator::OnUpdatedRTTAvailable( | 993 void NetworkQualityEstimator::OnUpdatedRTTAvailable( |
| 917 const Protocol protocol, | 994 SocketPerformanceWatcherFactory::Protocol protocol, |
| 918 const base::TimeDelta& rtt) { | 995 const base::TimeDelta& rtt) { |
| 919 DCHECK(thread_checker_.CalledOnValidThread()); | 996 DCHECK(thread_checker_.CalledOnValidThread()); |
| 920 | 997 |
| 921 switch (protocol) { | 998 switch (protocol) { |
| 922 case PROTOCOL_TCP: | 999 case SocketPerformanceWatcherFactory::PROTOCOL_TCP: |
| 923 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); | 1000 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); |
| 924 return; | 1001 return; |
| 925 case PROTOCOL_QUIC: | 1002 case SocketPerformanceWatcherFactory::PROTOCOL_QUIC: |
| 926 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); | 1003 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); |
| 927 return; | 1004 return; |
| 928 default: | 1005 default: |
| 929 NOTREACHED(); | 1006 NOTREACHED(); |
| 930 } | 1007 } |
| 931 } | 1008 } |
| 932 | 1009 |
| 933 void NetworkQualityEstimator::NotifyObserversOfRTT( | 1010 void NetworkQualityEstimator::NotifyObserversOfRTT( |
| 934 const RttObservation& observation) { | 1011 const RttObservation& observation) { |
| 935 FOR_EACH_OBSERVER( | 1012 FOR_EACH_OBSERVER( |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 986 | 1063 |
| 987 NetworkQualityEstimator::NetworkQuality& | 1064 NetworkQualityEstimator::NetworkQuality& |
| 988 NetworkQualityEstimator::NetworkQuality:: | 1065 NetworkQualityEstimator::NetworkQuality:: |
| 989 operator=(const NetworkQuality& other) { | 1066 operator=(const NetworkQuality& other) { |
| 990 rtt_ = other.rtt_; | 1067 rtt_ = other.rtt_; |
| 991 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | 1068 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; |
| 992 return *this; | 1069 return *this; |
| 993 } | 1070 } |
| 994 | 1071 |
| 995 } // namespace net | 1072 } // namespace net |
| OLD | NEW |