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 // SocketWatcherDelegate receives socket performance events from different | |
123 // SocketWatchers, and passes them to the NetworkQualityEstimator on the | |
124 // provided task runner. SocketWatcherDelegate is thread safe. | |
125 class NetworkQualityEstimator::SocketWatcherDelegate { | |
Ryan Sleevi
2016/04/04 17:30:09
Yeah, I don't think you should need this abstracti
tbansal1
2016/04/04 18:35:46
Is it okay if I keep this? The delegate interface
Ryan Sleevi
2016/04/04 18:53:37
Can you explain why you feel that way? I'd like to
tbansal1
2016/04/04 22:07:03
I have removed the SocketDelegate. I just thought
Ryan Sleevi
2016/04/04 22:34:04
As long as the copying of NQE's WeakPtr only happe
tbansal1
2016/04/04 23:46:32
Yes. Thanks for the detailed reply.
| |
126 public: | |
127 SocketWatcherDelegate( | |
128 scoped_refptr<base::SingleThreadTaskRunner> task_runner, | |
129 const base::WeakPtr<NetworkQualityEstimator>& network_quality_estimator) | |
130 : task_runner_(std::move(task_runner)), | |
131 network_quality_estimator_(network_quality_estimator) { | |
132 DCHECK(task_runner_); | |
133 } | |
134 | |
135 ~SocketWatcherDelegate() {} | |
136 | |
137 void OnUpdatedRTTAvailable(SocketPerformanceWatcherFactory::Protocol protocol, | |
138 const base::TimeDelta& rtt) { | |
139 task_runner_->PostTask( | |
140 FROM_HERE, base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable, | |
141 network_quality_estimator_, protocol, rtt)); | |
142 } | |
143 | |
144 private: | |
145 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; | |
146 | |
147 base::WeakPtr<NetworkQualityEstimator> network_quality_estimator_; | |
148 | |
149 DISALLOW_COPY_AND_ASSIGN(SocketWatcherDelegate); | |
150 }; | |
151 | |
152 // SocketWatcher implements SocketPerformanceWatcher, and notifies | |
153 // SocketWatcherDelegate of various socket performance events. SocketWatcher is | |
154 // not thread-safe. | |
155 class NetworkQualityEstimator::SocketWatcher : public SocketPerformanceWatcher { | |
156 public: | |
157 // |delegate| is guaranteed to be non-null during SocketWatcher's lifetime. | |
158 SocketWatcher(SocketPerformanceWatcherFactory::Protocol protocol, | |
159 SocketWatcherDelegate* delegate) | |
160 : protocol_(protocol), delegate_(delegate) { | |
161 DCHECK(delegate_); | |
162 } | |
163 | |
164 ~SocketWatcher() {} | |
165 | |
166 // SocketPerformanceWatcher implementation: | |
167 void OnUpdatedRTTAvailable(const base::TimeDelta& rtt) override { | |
168 DCHECK(thread_checker_.CalledOnValidThread()); | |
169 | |
170 delegate_->OnUpdatedRTTAvailable(protocol_, rtt); | |
171 } | |
172 | |
173 bool ShouldNotifyUpdatedRTT() const override { | |
174 DCHECK(thread_checker_.CalledOnValidThread()); | |
175 | |
176 return true; | |
177 } | |
178 | |
179 void Reset() override { DCHECK(thread_checker_.CalledOnValidThread()); } | |
180 | |
181 private: | |
182 // Transport layer protocol used by the socket that |this| is watching. | |
183 const SocketPerformanceWatcherFactory::Protocol protocol_; | |
184 | |
185 SocketWatcherDelegate* delegate_; | |
186 | |
187 base::ThreadChecker thread_checker_; | |
188 | |
189 DISALLOW_COPY_AND_ASSIGN(SocketWatcher); | |
190 }; | |
191 | |
192 // SocketWatcherFactory implements SocketPerformanceWatcherFactory, and is | |
193 // owned by NetworkQualityEstimator. SocketWatcherFactory is thread safe. | |
194 class NetworkQualityEstimator::SocketWatcherFactory | |
195 : public SocketPerformanceWatcherFactory { | |
196 public: | |
197 // |delegate| is guaranteed to be non-null during SocketWatcherFactory's | |
198 // lifetime. | |
199 explicit SocketWatcherFactory(SocketWatcherDelegate* delegate) | |
200 : delegate_(delegate) { | |
201 DCHECK(delegate_); | |
202 } | |
203 | |
204 ~SocketWatcherFactory() override {} | |
205 | |
206 // SocketPerformanceWatcherFactory implementation: | |
207 scoped_ptr<SocketPerformanceWatcher> CreateSocketPerformanceWatcher( | |
208 const Protocol protocol) override { | |
209 return scoped_ptr<SocketPerformanceWatcher>( | |
210 new SocketWatcher(protocol, delegate_)); | |
211 } | |
212 | |
213 private: | |
214 SocketWatcherDelegate* delegate_; | |
215 | |
216 DISALLOW_COPY_AND_ASSIGN(SocketWatcherFactory); | |
217 }; | |
218 | |
120 const int32_t NetworkQualityEstimator::kInvalidThroughput = 0; | 219 const int32_t NetworkQualityEstimator::kInvalidThroughput = 0; |
121 | 220 |
122 NetworkQualityEstimator::NetworkQualityEstimator( | 221 NetworkQualityEstimator::NetworkQualityEstimator( |
123 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, | 222 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, |
124 const std::map<std::string, std::string>& variation_params) | 223 const std::map<std::string, std::string>& variation_params) |
125 : NetworkQualityEstimator(std::move(external_estimates_provider), | 224 : NetworkQualityEstimator(std::move(external_estimates_provider), |
126 variation_params, | 225 variation_params, |
127 false, | 226 false, |
128 false) {} | 227 false) {} |
129 | 228 |
130 NetworkQualityEstimator::NetworkQualityEstimator( | 229 NetworkQualityEstimator::NetworkQualityEstimator( |
131 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, | 230 scoped_ptr<ExternalEstimateProvider> external_estimates_provider, |
132 const std::map<std::string, std::string>& variation_params, | 231 const std::map<std::string, std::string>& variation_params, |
133 bool allow_local_host_requests_for_tests, | 232 bool allow_local_host_requests_for_tests, |
134 bool allow_smaller_responses_for_tests) | 233 bool allow_smaller_responses_for_tests) |
135 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 234 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
136 allow_small_responses_(allow_smaller_responses_for_tests), | 235 allow_small_responses_(allow_smaller_responses_for_tests), |
137 last_connection_change_(base::TimeTicks::Now()), | 236 last_connection_change_(base::TimeTicks::Now()), |
138 current_network_id_( | 237 current_network_id_( |
139 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 238 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
140 std::string())), | 239 std::string())), |
141 downstream_throughput_kbps_observations_( | 240 downstream_throughput_kbps_observations_( |
142 GetWeightMultiplierPerSecond(variation_params)), | 241 GetWeightMultiplierPerSecond(variation_params)), |
143 rtt_observations_(GetWeightMultiplierPerSecond(variation_params)), | 242 rtt_observations_(GetWeightMultiplierPerSecond(variation_params)), |
144 external_estimate_provider_(std::move(external_estimates_provider)) { | 243 external_estimate_provider_(std::move(external_estimates_provider)), |
244 weak_ptr_factory_(this) { | |
145 static_assert(kMinRequestDurationMicroseconds > 0, | 245 static_assert(kMinRequestDurationMicroseconds > 0, |
146 "Minimum request duration must be > 0"); | 246 "Minimum request duration must be > 0"); |
147 static_assert(kDefaultHalfLifeSeconds > 0, | 247 static_assert(kDefaultHalfLifeSeconds > 0, |
148 "Default half life duration must be > 0"); | 248 "Default half life duration must be > 0"); |
149 static_assert(kMaximumNetworkQualityCacheSize > 0, | 249 static_assert(kMaximumNetworkQualityCacheSize > 0, |
150 "Size of the network quality cache must be > 0"); | 250 "Size of the network quality cache must be > 0"); |
151 // This limit should not be increased unless the logic for removing the | 251 // 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. | 252 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
153 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 253 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
154 "Size of the network quality cache must <= 10"); | 254 "Size of the network quality cache must <= 10"); |
155 | 255 |
156 ObtainOperatingParams(variation_params); | 256 ObtainOperatingParams(variation_params); |
157 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 257 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
158 if (external_estimate_provider_) { | 258 if (external_estimate_provider_) { |
159 RecordExternalEstimateProviderMetrics( | 259 RecordExternalEstimateProviderMetrics( |
160 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); | 260 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); |
161 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | 261 external_estimate_provider_->SetUpdatedEstimateDelegate(this); |
162 QueryExternalEstimateProvider(); | 262 QueryExternalEstimateProvider(); |
163 } else { | 263 } else { |
164 RecordExternalEstimateProviderMetrics( | 264 RecordExternalEstimateProviderMetrics( |
165 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); | 265 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); |
166 } | 266 } |
167 current_network_id_ = GetCurrentNetworkID(); | 267 current_network_id_ = GetCurrentNetworkID(); |
168 AddDefaultEstimates(); | 268 AddDefaultEstimates(); |
269 | |
270 delegate_.reset(new SocketWatcherDelegate(base::ThreadTaskRunnerHandle::Get(), | |
271 weak_ptr_factory_.GetWeakPtr())); | |
272 | |
273 watcher_factory_.reset(new SocketWatcherFactory(delegate_.get())); | |
169 } | 274 } |
170 | 275 |
171 // static | 276 // static |
172 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { | 277 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { |
173 return base::TimeDelta::Max(); | 278 return base::TimeDelta::Max(); |
174 } | 279 } |
175 | 280 |
176 void NetworkQualityEstimator::ObtainOperatingParams( | 281 void NetworkQualityEstimator::ObtainOperatingParams( |
177 const std::map<std::string, std::string>& variation_params) { | 282 const std::map<std::string, std::string>& variation_params) { |
178 DCHECK(thread_checker_.CalledOnValidThread()); | 283 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
369 DCHECK(thread_checker_.CalledOnValidThread()); | 474 DCHECK(thread_checker_.CalledOnValidThread()); |
370 throughput_observer_list_.AddObserver(throughput_observer); | 475 throughput_observer_list_.AddObserver(throughput_observer); |
371 } | 476 } |
372 | 477 |
373 void NetworkQualityEstimator::RemoveThroughputObserver( | 478 void NetworkQualityEstimator::RemoveThroughputObserver( |
374 ThroughputObserver* throughput_observer) { | 479 ThroughputObserver* throughput_observer) { |
375 DCHECK(thread_checker_.CalledOnValidThread()); | 480 DCHECK(thread_checker_.CalledOnValidThread()); |
376 throughput_observer_list_.RemoveObserver(throughput_observer); | 481 throughput_observer_list_.RemoveObserver(throughput_observer); |
377 } | 482 } |
378 | 483 |
484 SocketPerformanceWatcherFactory* | |
485 NetworkQualityEstimator::GetSocketPerformanceWatcherFactory() { | |
486 DCHECK(thread_checker_.CalledOnValidThread()); | |
487 | |
488 return watcher_factory_.get(); | |
489 } | |
490 | |
379 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, | 491 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, |
380 int32_t actual_value_msec) const { | 492 int32_t actual_value_msec) const { |
381 DCHECK(thread_checker_.CalledOnValidThread()); | 493 DCHECK(thread_checker_.CalledOnValidThread()); |
382 | 494 |
383 // Record the difference between the actual and the estimated value. | 495 // Record the difference between the actual and the estimated value. |
384 if (estimated_value_msec >= actual_value_msec) { | 496 if (estimated_value_msec >= actual_value_msec) { |
385 base::HistogramBase* difference_rtt = | 497 base::HistogramBase* difference_rtt = |
386 GetHistogram("DifferenceRTTEstimatedAndActual.", | 498 GetHistogram("DifferenceRTTEstimatedAndActual.", |
387 current_network_id_.type, 10 * 1000); // 10 seconds | 499 current_network_id_.type, 10 * 1000); // 10 seconds |
388 difference_rtt->Add(estimated_value_msec - actual_value_msec); | 500 difference_rtt->Add(estimated_value_msec - actual_value_msec); |
(...skipping 508 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
897 } | 1009 } |
898 DCHECK_LT(cached_network_qualities_.size(), | 1010 DCHECK_LT(cached_network_qualities_.size(), |
899 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 1011 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
900 | 1012 |
901 cached_network_qualities_.insert(std::make_pair( | 1013 cached_network_qualities_.insert(std::make_pair( |
902 current_network_id_, CachedNetworkQuality(network_quality))); | 1014 current_network_id_, CachedNetworkQuality(network_quality))); |
903 DCHECK_LE(cached_network_qualities_.size(), | 1015 DCHECK_LE(cached_network_qualities_.size(), |
904 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 1016 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
905 } | 1017 } |
906 | 1018 |
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( | 1019 void NetworkQualityEstimator::OnUpdatedRTTAvailable( |
917 const Protocol protocol, | 1020 SocketPerformanceWatcherFactory::Protocol protocol, |
918 const base::TimeDelta& rtt) { | 1021 const base::TimeDelta& rtt) { |
919 DCHECK(thread_checker_.CalledOnValidThread()); | 1022 DCHECK(thread_checker_.CalledOnValidThread()); |
920 | 1023 |
921 switch (protocol) { | 1024 switch (protocol) { |
922 case PROTOCOL_TCP: | 1025 case SocketPerformanceWatcherFactory::PROTOCOL_TCP: |
923 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); | 1026 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); |
924 return; | 1027 return; |
925 case PROTOCOL_QUIC: | 1028 case SocketPerformanceWatcherFactory::PROTOCOL_QUIC: |
926 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); | 1029 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); |
927 return; | 1030 return; |
928 default: | 1031 default: |
929 NOTREACHED(); | 1032 NOTREACHED(); |
930 } | 1033 } |
931 } | 1034 } |
932 | 1035 |
933 void NetworkQualityEstimator::NotifyObserversOfRTT( | 1036 void NetworkQualityEstimator::NotifyObserversOfRTT( |
934 const RttObservation& observation) { | 1037 const RttObservation& observation) { |
935 FOR_EACH_OBSERVER( | 1038 FOR_EACH_OBSERVER( |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
986 | 1089 |
987 NetworkQualityEstimator::NetworkQuality& | 1090 NetworkQualityEstimator::NetworkQuality& |
988 NetworkQualityEstimator::NetworkQuality:: | 1091 NetworkQualityEstimator::NetworkQuality:: |
989 operator=(const NetworkQuality& other) { | 1092 operator=(const NetworkQuality& other) { |
990 rtt_ = other.rtt_; | 1093 rtt_ = other.rtt_; |
991 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | 1094 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; |
992 return *this; | 1095 return *this; |
993 } | 1096 } |
994 | 1097 |
995 } // namespace net | 1098 } // namespace net |
OLD | NEW |