| 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/nqe/network_quality_estimator.h" | 5 #include "net/nqe/network_quality_estimator.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cmath> | 8 #include <cmath> |
| 9 #include <limits> | 9 #include <limits> |
| 10 #include <utility> | 10 #include <utility> |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 127 const char prefix[] = "NQE."; | 127 const char prefix[] = "NQE."; |
| 128 return base::Histogram::FactoryGet( | 128 return base::Histogram::FactoryGet( |
| 129 prefix + statistic_name + GetNameForConnectionType(type), kLowerLimit, | 129 prefix + statistic_name + GetNameForConnectionType(type), kLowerLimit, |
| 130 max_limit, kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag); | 130 max_limit, kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 131 } | 131 } |
| 132 | 132 |
| 133 bool GetValueForVariationParam( | 133 bool GetValueForVariationParam( |
| 134 const std::map<std::string, std::string>& variation_params, | 134 const std::map<std::string, std::string>& variation_params, |
| 135 const std::string& parameter_name, | 135 const std::string& parameter_name, |
| 136 int32_t* variations_value) { | 136 int32_t* variations_value) { |
| 137 auto it = variation_params.find(parameter_name); | 137 const auto it = variation_params.find(parameter_name); |
| 138 return it != variation_params.end() && | 138 return it != variation_params.end() && |
| 139 base::StringToInt(it->second, variations_value); | 139 base::StringToInt(it->second, variations_value); |
| 140 } | 140 } |
| 141 | 141 |
| 142 // Returns the algorithm that should be used for computing effective connection |
| 143 // type based on field trial params. Returns an empty string if a valid |
| 144 // algorithm paramter is not present in the field trial params. |
| 145 std::string GetEffectiveConnectionTypeAlgorithm( |
| 146 const std::map<std::string, std::string>& variation_params) { |
| 147 const auto it = variation_params.find("effective_connection_type_algorithm"); |
| 148 if (it == variation_params.end()) |
| 149 return std::string(); |
| 150 return it->second; |
| 151 } |
| 152 |
| 142 net::NetworkQualityObservationSource ProtocolSourceToObservationSource( | 153 net::NetworkQualityObservationSource ProtocolSourceToObservationSource( |
| 143 net::SocketPerformanceWatcherFactory::Protocol protocol) { | 154 net::SocketPerformanceWatcherFactory::Protocol protocol) { |
| 144 switch (protocol) { | 155 switch (protocol) { |
| 145 case net::SocketPerformanceWatcherFactory::PROTOCOL_TCP: | 156 case net::SocketPerformanceWatcherFactory::PROTOCOL_TCP: |
| 146 return net::NETWORK_QUALITY_OBSERVATION_SOURCE_TCP; | 157 return net::NETWORK_QUALITY_OBSERVATION_SOURCE_TCP; |
| 147 case net::SocketPerformanceWatcherFactory::PROTOCOL_QUIC: | 158 case net::SocketPerformanceWatcherFactory::PROTOCOL_QUIC: |
| 148 return net::NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC; | 159 return net::NETWORK_QUALITY_OBSERVATION_SOURCE_QUIC; |
| 149 } | 160 } |
| 150 NOTREACHED(); | 161 NOTREACHED(); |
| 151 return net::NETWORK_QUALITY_OBSERVATION_SOURCE_TCP; | 162 return net::NETWORK_QUALITY_OBSERVATION_SOURCE_TCP; |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 : NetworkQualityEstimator(std::move(external_estimates_provider), | 196 : NetworkQualityEstimator(std::move(external_estimates_provider), |
| 186 variation_params, | 197 variation_params, |
| 187 false, | 198 false, |
| 188 false) {} | 199 false) {} |
| 189 | 200 |
| 190 NetworkQualityEstimator::NetworkQualityEstimator( | 201 NetworkQualityEstimator::NetworkQualityEstimator( |
| 191 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, | 202 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, |
| 192 const std::map<std::string, std::string>& variation_params, | 203 const std::map<std::string, std::string>& variation_params, |
| 193 bool use_local_host_requests_for_tests, | 204 bool use_local_host_requests_for_tests, |
| 194 bool use_smaller_responses_for_tests) | 205 bool use_smaller_responses_for_tests) |
| 195 : use_localhost_requests_(use_local_host_requests_for_tests), | 206 : algorithm_name_to_enum_({{"HttpRTTAndDownstreamThroughput", |
| 207 EffectiveConnectionTypeAlgorithm:: |
| 208 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT}}), |
| 209 use_localhost_requests_(use_local_host_requests_for_tests), |
| 196 use_small_responses_(use_smaller_responses_for_tests), | 210 use_small_responses_(use_smaller_responses_for_tests), |
| 197 weight_multiplier_per_second_( | 211 weight_multiplier_per_second_( |
| 198 GetWeightMultiplierPerSecond(variation_params)), | 212 GetWeightMultiplierPerSecond(variation_params)), |
| 213 effective_connection_type_algorithm_( |
| 214 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm( |
| 215 variation_params)) == algorithm_name_to_enum_.end() |
| 216 ? kDefaultEffectiveConnectionTypeAlgorithm |
| 217 : algorithm_name_to_enum_ |
| 218 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) |
| 219 ->second), |
| 199 tick_clock_(new base::DefaultTickClock()), | 220 tick_clock_(new base::DefaultTickClock()), |
| 200 effective_connection_type_recomputation_interval_( | 221 effective_connection_type_recomputation_interval_( |
| 201 base::TimeDelta::FromSeconds(15)), | 222 base::TimeDelta::FromSeconds(15)), |
| 202 last_connection_change_(tick_clock_->NowTicks()), | 223 last_connection_change_(tick_clock_->NowTicks()), |
| 203 current_network_id_( | 224 current_network_id_( |
| 204 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 225 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 205 std::string())), | 226 std::string())), |
| 206 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), | 227 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), |
| 207 rtt_observations_(weight_multiplier_per_second_), | 228 rtt_observations_(weight_multiplier_per_second_), |
| 208 external_estimate_provider_(std::move(external_estimates_provider)), | 229 external_estimate_provider_(std::move(external_estimates_provider)), |
| 209 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 230 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| 210 weak_ptr_factory_(this) { | 231 weak_ptr_factory_(this) { |
| 211 static_assert(kDefaultHalfLifeSeconds > 0, | 232 static_assert(kDefaultHalfLifeSeconds > 0, |
| 212 "Default half life duration must be > 0"); | 233 "Default half life duration must be > 0"); |
| 213 static_assert(kMaximumNetworkQualityCacheSize > 0, | 234 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 214 "Size of the network quality cache must be > 0"); | 235 "Size of the network quality cache must be > 0"); |
| 215 // This limit should not be increased unless the logic for removing the | 236 // This limit should not be increased unless the logic for removing the |
| 216 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. | 237 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 217 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 238 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 218 "Size of the network quality cache must <= 10"); | 239 "Size of the network quality cache must <= 10"); |
| 240 // None of the algorithms can have an empty name. |
| 241 DCHECK(algorithm_name_to_enum_.end() == |
| 242 algorithm_name_to_enum_.find(std::string())); |
| 243 |
| 244 DCHECK_EQ(algorithm_name_to_enum_.size(), |
| 245 static_cast<size_t>(EffectiveConnectionTypeAlgorithm:: |
| 246 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST)); |
| 247 DCHECK_NE(EffectiveConnectionTypeAlgorithm:: |
| 248 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST, |
| 249 effective_connection_type_algorithm_); |
| 219 | 250 |
| 220 ObtainOperatingParams(variation_params); | 251 ObtainOperatingParams(variation_params); |
| 221 ObtainEffectiveConnectionTypeModelParams(variation_params); | 252 ObtainEffectiveConnectionTypeModelParams(variation_params); |
| 222 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 253 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 223 if (external_estimate_provider_) { | 254 if (external_estimate_provider_) { |
| 224 RecordExternalEstimateProviderMetrics( | 255 RecordExternalEstimateProviderMetrics( |
| 225 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); | 256 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); |
| 226 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | 257 external_estimate_provider_->SetUpdatedEstimateDelegate(this); |
| 227 } else { | 258 } else { |
| 228 RecordExternalEstimateProviderMetrics( | 259 RecordExternalEstimateProviderMetrics( |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 749 NetworkQualityEstimator::GetEffectiveConnectionType() const { | 780 NetworkQualityEstimator::GetEffectiveConnectionType() const { |
| 750 DCHECK(thread_checker_.CalledOnValidThread()); | 781 DCHECK(thread_checker_.CalledOnValidThread()); |
| 751 return GetRecentEffectiveConnectionType(base::TimeTicks()); | 782 return GetRecentEffectiveConnectionType(base::TimeTicks()); |
| 752 } | 783 } |
| 753 | 784 |
| 754 NetworkQualityEstimator::EffectiveConnectionType | 785 NetworkQualityEstimator::EffectiveConnectionType |
| 755 NetworkQualityEstimator::GetRecentEffectiveConnectionType( | 786 NetworkQualityEstimator::GetRecentEffectiveConnectionType( |
| 756 const base::TimeTicks& start_time) const { | 787 const base::TimeTicks& start_time) const { |
| 757 DCHECK(thread_checker_.CalledOnValidThread()); | 788 DCHECK(thread_checker_.CalledOnValidThread()); |
| 758 | 789 |
| 790 if (effective_connection_type_algorithm_ == |
| 791 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { |
| 792 return GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( |
| 793 start_time); |
| 794 } |
| 795 // Add additional algorithms here. |
| 796 NOTREACHED(); |
| 797 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 798 } |
| 799 |
| 800 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: |
| 801 GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( |
| 802 const base::TimeTicks& start_time) const { |
| 803 DCHECK(thread_checker_.CalledOnValidThread()); |
| 804 |
| 759 // If the device is currently offline, then return | 805 // If the device is currently offline, then return |
| 760 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. | 806 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. |
| 761 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) | 807 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) |
| 762 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; | 808 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; |
| 763 | 809 |
| 764 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); | 810 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); |
| 765 if (!GetRecentHttpRTTMedian(start_time, &http_rtt)) | 811 if (!GetRecentHttpRTTMedian(start_time, &http_rtt)) |
| 766 http_rtt = nqe::internal::InvalidRTT(); | 812 http_rtt = nqe::internal::InvalidRTT(); |
| 767 | 813 |
| 768 int32_t kbps = nqe::internal::kInvalidThroughput; | 814 int32_t kbps = nqe::internal::kInvalidThroughput; |
| 769 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) | 815 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) |
| 770 kbps = nqe::internal::kInvalidThroughput; | 816 kbps = nqe::internal::kInvalidThroughput; |
| 771 | 817 |
| 772 if (http_rtt == nqe::internal::InvalidRTT() && | 818 if (http_rtt == nqe::internal::InvalidRTT() || |
| 773 kbps == nqe::internal::kInvalidThroughput) { | 819 kbps == nqe::internal::kInvalidThroughput) { |
| 774 // Quality of the current network is unknown. | 820 // Quality of the current network is unknown. |
| 775 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 821 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 776 } | 822 } |
| 777 | 823 |
| 778 // Search from the slowest connection type to the fastest to find the | 824 // Search from the slowest connection type to the fastest to find the |
| 779 // EffectiveConnectionType that best matches the current connection's | 825 // EffectiveConnectionType that best matches the current connection's |
| 780 // performance. The match is done by comparing RTT and throughput. | 826 // performance. The match is done by comparing RTT and throughput. |
| 781 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 827 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 782 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | 828 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1191 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1237 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1192 DCHECK(thread_checker_.CalledOnValidThread()); | 1238 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1193 | 1239 |
| 1194 // TODO(tbansal): Add hysteresis in the notification. | 1240 // TODO(tbansal): Add hysteresis in the notification. |
| 1195 FOR_EACH_OBSERVER( | 1241 FOR_EACH_OBSERVER( |
| 1196 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1242 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1197 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1243 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1198 } | 1244 } |
| 1199 | 1245 |
| 1200 } // namespace net | 1246 } // namespace net |
| OLD | NEW |