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/bind.h" |
14 #include "base/logging.h" | 15 #include "base/logging.h" |
15 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
16 #include "base/metrics/histogram_base.h" | 17 #include "base/metrics/histogram_base.h" |
17 #include "base/strings/string_number_conversions.h" | 18 #include "base/strings/string_number_conversions.h" |
| 19 #include "base/thread_task_runner_handle.h" |
18 #include "build/build_config.h" | 20 #include "build/build_config.h" |
19 #include "net/base/load_flags.h" | 21 #include "net/base/load_flags.h" |
20 #include "net/base/load_timing_info.h" | 22 #include "net/base/load_timing_info.h" |
21 #include "net/base/network_interfaces.h" | 23 #include "net/base/network_interfaces.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" |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
134 bool allow_smaller_responses_for_tests) | 136 bool allow_smaller_responses_for_tests) |
135 : allow_localhost_requests_(allow_local_host_requests_for_tests), | 137 : allow_localhost_requests_(allow_local_host_requests_for_tests), |
136 allow_small_responses_(allow_smaller_responses_for_tests), | 138 allow_small_responses_(allow_smaller_responses_for_tests), |
137 last_connection_change_(base::TimeTicks::Now()), | 139 last_connection_change_(base::TimeTicks::Now()), |
138 current_network_id_( | 140 current_network_id_( |
139 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 141 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
140 std::string())), | 142 std::string())), |
141 downstream_throughput_kbps_observations_( | 143 downstream_throughput_kbps_observations_( |
142 GetWeightMultiplierPerSecond(variation_params)), | 144 GetWeightMultiplierPerSecond(variation_params)), |
143 rtt_observations_(GetWeightMultiplierPerSecond(variation_params)), | 145 rtt_observations_(GetWeightMultiplierPerSecond(variation_params)), |
144 external_estimate_provider_(std::move(external_estimates_provider)) { | 146 external_estimate_provider_(std::move(external_estimates_provider)), |
| 147 weak_ptr_factory_(this) { |
145 static_assert(kMinRequestDurationMicroseconds > 0, | 148 static_assert(kMinRequestDurationMicroseconds > 0, |
146 "Minimum request duration must be > 0"); | 149 "Minimum request duration must be > 0"); |
147 static_assert(kDefaultHalfLifeSeconds > 0, | 150 static_assert(kDefaultHalfLifeSeconds > 0, |
148 "Default half life duration must be > 0"); | 151 "Default half life duration must be > 0"); |
149 static_assert(kMaximumNetworkQualityCacheSize > 0, | 152 static_assert(kMaximumNetworkQualityCacheSize > 0, |
150 "Size of the network quality cache must be > 0"); | 153 "Size of the network quality cache must be > 0"); |
151 // This limit should not be increased unless the logic for removing the | 154 // 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. | 155 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
153 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 156 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
154 "Size of the network quality cache must <= 10"); | 157 "Size of the network quality cache must <= 10"); |
155 | 158 |
156 ObtainOperatingParams(variation_params); | 159 ObtainOperatingParams(variation_params); |
157 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 160 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
158 if (external_estimate_provider_) { | 161 if (external_estimate_provider_) { |
159 RecordExternalEstimateProviderMetrics( | 162 RecordExternalEstimateProviderMetrics( |
160 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); | 163 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); |
161 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | 164 external_estimate_provider_->SetUpdatedEstimateDelegate(this); |
162 QueryExternalEstimateProvider(); | 165 QueryExternalEstimateProvider(); |
163 } else { | 166 } else { |
164 RecordExternalEstimateProviderMetrics( | 167 RecordExternalEstimateProviderMetrics( |
165 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); | 168 EXTERNAL_ESTIMATE_PROVIDER_STATUS_NOT_AVAILABLE); |
166 } | 169 } |
167 current_network_id_ = GetCurrentNetworkID(); | 170 current_network_id_ = GetCurrentNetworkID(); |
168 AddDefaultEstimates(); | 171 AddDefaultEstimates(); |
| 172 |
| 173 watcher_factory_.reset(new SocketWatcherFactory( |
| 174 base::ThreadTaskRunnerHandle::Get(), |
| 175 base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable, |
| 176 GetWeakPtr()))); |
169 } | 177 } |
170 | 178 |
171 // static | 179 // static |
172 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { | 180 const base::TimeDelta NetworkQualityEstimator::InvalidRTT() { |
173 return base::TimeDelta::Max(); | 181 return base::TimeDelta::Max(); |
174 } | 182 } |
175 | 183 |
176 void NetworkQualityEstimator::ObtainOperatingParams( | 184 void NetworkQualityEstimator::ObtainOperatingParams( |
177 const std::map<std::string, std::string>& variation_params) { | 185 const std::map<std::string, std::string>& variation_params) { |
178 DCHECK(thread_checker_.CalledOnValidThread()); | 186 DCHECK(thread_checker_.CalledOnValidThread()); |
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 DCHECK(thread_checker_.CalledOnValidThread()); | 377 DCHECK(thread_checker_.CalledOnValidThread()); |
370 throughput_observer_list_.AddObserver(throughput_observer); | 378 throughput_observer_list_.AddObserver(throughput_observer); |
371 } | 379 } |
372 | 380 |
373 void NetworkQualityEstimator::RemoveThroughputObserver( | 381 void NetworkQualityEstimator::RemoveThroughputObserver( |
374 ThroughputObserver* throughput_observer) { | 382 ThroughputObserver* throughput_observer) { |
375 DCHECK(thread_checker_.CalledOnValidThread()); | 383 DCHECK(thread_checker_.CalledOnValidThread()); |
376 throughput_observer_list_.RemoveObserver(throughput_observer); | 384 throughput_observer_list_.RemoveObserver(throughput_observer); |
377 } | 385 } |
378 | 386 |
| 387 SocketPerformanceWatcherFactory* |
| 388 NetworkQualityEstimator::GetSocketPerformanceWatcherFactory() { |
| 389 DCHECK(thread_checker_.CalledOnValidThread()); |
| 390 |
| 391 return watcher_factory_.get(); |
| 392 } |
| 393 |
379 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, | 394 void NetworkQualityEstimator::RecordRTTUMA(int32_t estimated_value_msec, |
380 int32_t actual_value_msec) const { | 395 int32_t actual_value_msec) const { |
381 DCHECK(thread_checker_.CalledOnValidThread()); | 396 DCHECK(thread_checker_.CalledOnValidThread()); |
382 | 397 |
383 // Record the difference between the actual and the estimated value. | 398 // Record the difference between the actual and the estimated value. |
384 if (estimated_value_msec >= actual_value_msec) { | 399 if (estimated_value_msec >= actual_value_msec) { |
385 base::HistogramBase* difference_rtt = | 400 base::HistogramBase* difference_rtt = |
386 GetHistogram("DifferenceRTTEstimatedAndActual.", | 401 GetHistogram("DifferenceRTTEstimatedAndActual.", |
387 current_network_id_.type, 10 * 1000); // 10 seconds | 402 current_network_id_.type, 10 * 1000); // 10 seconds |
388 difference_rtt->Add(estimated_value_msec - actual_value_msec); | 403 difference_rtt->Add(estimated_value_msec - actual_value_msec); |
(...skipping 237 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 // a higher percentile RTT will have a longer RTT than a lower percentile. | 641 // a higher percentile RTT will have a longer RTT than a lower percentile. |
627 base::TimeDelta rtt = InvalidRTT(); | 642 base::TimeDelta rtt = InvalidRTT(); |
628 std::vector<ObservationSource> disallowed_observation_sources; | 643 std::vector<ObservationSource> disallowed_observation_sources; |
629 disallowed_observation_sources.push_back(TCP); | 644 disallowed_observation_sources.push_back(TCP); |
630 disallowed_observation_sources.push_back(QUIC); | 645 disallowed_observation_sources.push_back(QUIC); |
631 rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile, | 646 rtt_observations_.GetPercentile(begin_timestamp, &rtt, percentile, |
632 disallowed_observation_sources); | 647 disallowed_observation_sources); |
633 return rtt; | 648 return rtt; |
634 } | 649 } |
635 | 650 |
| 651 NetworkQualityEstimator::SocketWatcherFactory::SocketWatcherFactory( |
| 652 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, |
| 653 RTTUpdateCallback rtt_update_callback) |
| 654 : task_runner_(task_runner), |
| 655 rtt_update_callback_(rtt_update_callback), |
| 656 weak_ptr_factory_(this) { |
| 657 DCHECK(task_runner_); |
| 658 } |
| 659 |
| 660 NetworkQualityEstimator::SocketWatcherFactory::~SocketWatcherFactory() {} |
| 661 |
| 662 scoped_ptr<SocketPerformanceWatcher> |
| 663 NetworkQualityEstimator::SocketWatcherFactory::CreateSocketPerformanceWatcher( |
| 664 const Protocol protocol) { |
| 665 return scoped_ptr<SocketPerformanceWatcher>(new SocketPerformanceWatcher( |
| 666 protocol, base::Bind(&SocketWatcherFactory::OnUpdatedRTTAvailable, |
| 667 weak_ptr_factory_.GetWeakPtr()), |
| 668 base::Bind(&SocketWatcherFactory::OnWatcherReset, |
| 669 weak_ptr_factory_.GetWeakPtr()))); |
| 670 } |
| 671 |
| 672 void NetworkQualityEstimator::SocketWatcherFactory::OnUpdatedRTTAvailable( |
| 673 const Protocol protocol, |
| 674 const base::TimeDelta& rtt) { |
| 675 task_runner_->PostTask(FROM_HERE, |
| 676 base::Bind(rtt_update_callback_, protocol, rtt)); |
| 677 } |
| 678 |
| 679 void NetworkQualityEstimator::SocketWatcherFactory::OnWatcherReset() { |
| 680 // Nothing needs to be done for RTT observations since SocketWatcherFactory |
| 681 // does not maintain any watcher-specific state. |
| 682 } |
| 683 |
636 int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal( | 684 int32_t NetworkQualityEstimator::GetDownlinkThroughputKbpsEstimateInternal( |
637 const base::TimeTicks& begin_timestamp, | 685 const base::TimeTicks& begin_timestamp, |
638 int percentile) const { | 686 int percentile) const { |
639 DCHECK(thread_checker_.CalledOnValidThread()); | 687 DCHECK(thread_checker_.CalledOnValidThread()); |
640 DCHECK_GE(percentile, 0); | 688 DCHECK_GE(percentile, 0); |
641 DCHECK_LE(percentile, 100); | 689 DCHECK_LE(percentile, 100); |
642 if (downstream_throughput_kbps_observations_.Size() == 0) | 690 if (downstream_throughput_kbps_observations_.Size() == 0) |
643 return kInvalidThroughput; | 691 return kInvalidThroughput; |
644 | 692 |
645 // Throughput observations are sorted by kbps from slowest to fastest, | 693 // Throughput observations are sorted by kbps from slowest to fastest, |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
897 } | 945 } |
898 DCHECK_LT(cached_network_qualities_.size(), | 946 DCHECK_LT(cached_network_qualities_.size(), |
899 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 947 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
900 | 948 |
901 cached_network_qualities_.insert(std::make_pair( | 949 cached_network_qualities_.insert(std::make_pair( |
902 current_network_id_, CachedNetworkQuality(network_quality))); | 950 current_network_id_, CachedNetworkQuality(network_quality))); |
903 DCHECK_LE(cached_network_qualities_.size(), | 951 DCHECK_LE(cached_network_qualities_.size(), |
904 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); | 952 static_cast<size_t>(kMaximumNetworkQualityCacheSize)); |
905 } | 953 } |
906 | 954 |
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( | 955 void NetworkQualityEstimator::OnUpdatedRTTAvailable( |
917 const Protocol protocol, | 956 SocketPerformanceWatcherFactory::Protocol protocol, |
918 const base::TimeDelta& rtt) { | 957 const base::TimeDelta& rtt) { |
919 DCHECK(thread_checker_.CalledOnValidThread()); | 958 DCHECK(thread_checker_.CalledOnValidThread()); |
920 | 959 |
921 switch (protocol) { | 960 switch (protocol) { |
922 case PROTOCOL_TCP: | 961 case SocketPerformanceWatcherFactory::PROTOCOL_TCP: |
923 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); | 962 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), TCP)); |
924 return; | 963 return; |
925 case PROTOCOL_QUIC: | 964 case SocketPerformanceWatcherFactory::PROTOCOL_QUIC: |
926 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); | 965 NotifyObserversOfRTT(RttObservation(rtt, base::TimeTicks::Now(), QUIC)); |
927 return; | 966 return; |
928 default: | 967 default: |
929 NOTREACHED(); | 968 NOTREACHED(); |
930 } | 969 } |
931 } | 970 } |
932 | 971 |
933 void NetworkQualityEstimator::NotifyObserversOfRTT( | 972 void NetworkQualityEstimator::NotifyObserversOfRTT( |
934 const RttObservation& observation) { | 973 const RttObservation& observation) { |
935 FOR_EACH_OBSERVER( | 974 FOR_EACH_OBSERVER( |
936 RTTObserver, rtt_observer_list_, | 975 RTTObserver, rtt_observer_list_, |
937 OnRTTObservation(observation.value.InMilliseconds(), | 976 OnRTTObservation(observation.value.InMilliseconds(), |
938 observation.timestamp, observation.source)); | 977 observation.timestamp, observation.source)); |
939 } | 978 } |
940 | 979 |
941 void NetworkQualityEstimator::NotifyObserversOfThroughput( | 980 void NetworkQualityEstimator::NotifyObserversOfThroughput( |
942 const ThroughputObservation& observation) { | 981 const ThroughputObservation& observation) { |
943 FOR_EACH_OBSERVER( | 982 FOR_EACH_OBSERVER( |
944 ThroughputObserver, throughput_observer_list_, | 983 ThroughputObserver, throughput_observer_list_, |
945 OnThroughputObservation(observation.value, observation.timestamp, | 984 OnThroughputObservation(observation.value, observation.timestamp, |
946 observation.source)); | 985 observation.source)); |
947 } | 986 } |
948 | 987 |
| 988 base::WeakPtr<NetworkQualityEstimator> NetworkQualityEstimator::GetWeakPtr() { |
| 989 DCHECK(thread_checker_.CalledOnValidThread()); |
| 990 |
| 991 return weak_ptr_factory_.GetWeakPtr(); |
| 992 } |
| 993 |
949 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | 994 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( |
950 const NetworkQuality& network_quality) | 995 const NetworkQuality& network_quality) |
951 : last_update_time_(base::TimeTicks::Now()), | 996 : last_update_time_(base::TimeTicks::Now()), |
952 network_quality_(network_quality) { | 997 network_quality_(network_quality) { |
953 } | 998 } |
954 | 999 |
955 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( | 1000 NetworkQualityEstimator::CachedNetworkQuality::CachedNetworkQuality( |
956 const CachedNetworkQuality& other) | 1001 const CachedNetworkQuality& other) |
957 : last_update_time_(other.last_update_time_), | 1002 : last_update_time_(other.last_update_time_), |
958 network_quality_(other.network_quality_) { | 1003 network_quality_(other.network_quality_) { |
(...skipping 27 matching lines...) Expand all Loading... |
986 | 1031 |
987 NetworkQualityEstimator::NetworkQuality& | 1032 NetworkQualityEstimator::NetworkQuality& |
988 NetworkQualityEstimator::NetworkQuality:: | 1033 NetworkQualityEstimator::NetworkQuality:: |
989 operator=(const NetworkQuality& other) { | 1034 operator=(const NetworkQuality& other) { |
990 rtt_ = other.rtt_; | 1035 rtt_ = other.rtt_; |
991 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; | 1036 downstream_throughput_kbps_ = other.downstream_throughput_kbps_; |
992 return *this; | 1037 return *this; |
993 } | 1038 } |
994 | 1039 |
995 } // namespace net | 1040 } // namespace net |
OLD | NEW |