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/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("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 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 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 : use_localhost_requests_(use_local_host_requests_for_tests), |
| 196 use_small_responses_(use_smaller_responses_for_tests), | 207 use_small_responses_(use_smaller_responses_for_tests), |
| 197 weight_multiplier_per_second_( | 208 weight_multiplier_per_second_( |
| 198 GetWeightMultiplierPerSecond(variation_params)), | 209 GetWeightMultiplierPerSecond(variation_params)), |
| 210 algorithm_( | |
| 211 stringToAlgorithm_.find(GetEffectiveConnectionTypeAlgorithm( | |
| 212 variation_params)) == stringToAlgorithm_.end() | |
| 213 ? kDefaultEffectiveConnectionTypeAlgorithm | |
| 214 : stringToAlgorithm_ | |
| 215 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) | |
| 216 ->second), | |
| 199 tick_clock_(new base::DefaultTickClock()), | 217 tick_clock_(new base::DefaultTickClock()), |
| 200 effective_connection_type_recomputation_interval_( | 218 effective_connection_type_recomputation_interval_( |
| 201 base::TimeDelta::FromSeconds(15)), | 219 base::TimeDelta::FromSeconds(15)), |
| 202 last_connection_change_(tick_clock_->NowTicks()), | 220 last_connection_change_(tick_clock_->NowTicks()), |
| 203 current_network_id_( | 221 current_network_id_( |
| 204 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 222 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
| 205 std::string())), | 223 std::string())), |
| 206 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), | 224 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), |
| 207 rtt_observations_(weight_multiplier_per_second_), | 225 rtt_observations_(weight_multiplier_per_second_), |
| 208 external_estimate_provider_(std::move(external_estimates_provider)), | 226 external_estimate_provider_(std::move(external_estimates_provider)), |
| 209 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 227 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
| 210 weak_ptr_factory_(this) { | 228 weak_ptr_factory_(this) { |
| 211 static_assert(kDefaultHalfLifeSeconds > 0, | 229 static_assert(kDefaultHalfLifeSeconds > 0, |
| 212 "Default half life duration must be > 0"); | 230 "Default half life duration must be > 0"); |
| 213 static_assert(kMaximumNetworkQualityCacheSize > 0, | 231 static_assert(kMaximumNetworkQualityCacheSize > 0, |
| 214 "Size of the network quality cache must be > 0"); | 232 "Size of the network quality cache must be > 0"); |
| 215 // This limit should not be increased unless the logic for removing the | 233 // 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. | 234 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue. |
| 217 static_assert(kMaximumNetworkQualityCacheSize <= 10, | 235 static_assert(kMaximumNetworkQualityCacheSize <= 10, |
| 218 "Size of the network quality cache must <= 10"); | 236 "Size of the network quality cache must <= 10"); |
| 237 // None of the algorithms can have an empty name. | |
| 238 DCHECK(stringToAlgorithm_.end() == stringToAlgorithm_.find(std::string())); | |
|
bengr
2016/06/08 23:33:11
Construction of the map should go write before thi
tbansal1
2016/06/08 23:48:29
Not doing this as discussed offline.
| |
| 239 | |
| 240 DCHECK_EQ(stringToAlgorithm_.size(), | |
| 241 static_cast<size_t>(EffectiveConnectionTypeAlgorithm:: | |
| 242 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST)); | |
| 243 DCHECK_NE(EffectiveConnectionTypeAlgorithm:: | |
| 244 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST, | |
| 245 algorithm_); | |
| 219 | 246 |
| 220 ObtainOperatingParams(variation_params); | 247 ObtainOperatingParams(variation_params); |
| 221 ObtainEffectiveConnectionTypeModelParams(variation_params); | 248 ObtainEffectiveConnectionTypeModelParams(variation_params); |
| 222 NetworkChangeNotifier::AddConnectionTypeObserver(this); | 249 NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 223 if (external_estimate_provider_) { | 250 if (external_estimate_provider_) { |
| 224 RecordExternalEstimateProviderMetrics( | 251 RecordExternalEstimateProviderMetrics( |
| 225 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); | 252 EXTERNAL_ESTIMATE_PROVIDER_STATUS_AVAILABLE); |
| 226 external_estimate_provider_->SetUpdatedEstimateDelegate(this); | 253 external_estimate_provider_->SetUpdatedEstimateDelegate(this); |
| 227 } else { | 254 } else { |
| 228 RecordExternalEstimateProviderMetrics( | 255 RecordExternalEstimateProviderMetrics( |
| (...skipping 520 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 749 NetworkQualityEstimator::GetEffectiveConnectionType() const { | 776 NetworkQualityEstimator::GetEffectiveConnectionType() const { |
| 750 DCHECK(thread_checker_.CalledOnValidThread()); | 777 DCHECK(thread_checker_.CalledOnValidThread()); |
| 751 return GetRecentEffectiveConnectionType(base::TimeTicks()); | 778 return GetRecentEffectiveConnectionType(base::TimeTicks()); |
| 752 } | 779 } |
| 753 | 780 |
| 754 NetworkQualityEstimator::EffectiveConnectionType | 781 NetworkQualityEstimator::EffectiveConnectionType |
| 755 NetworkQualityEstimator::GetRecentEffectiveConnectionType( | 782 NetworkQualityEstimator::GetRecentEffectiveConnectionType( |
| 756 const base::TimeTicks& start_time) const { | 783 const base::TimeTicks& start_time) const { |
| 757 DCHECK(thread_checker_.CalledOnValidThread()); | 784 DCHECK(thread_checker_.CalledOnValidThread()); |
| 758 | 785 |
| 786 if (algorithm_ == | |
| 787 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { | |
| 788 return GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | |
| 789 start_time); | |
| 790 } | |
| 791 // Add additional algorithms here. | |
| 792 NOTREACHED(); | |
| 793 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | |
| 794 } | |
| 795 | |
| 796 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: | |
| 797 GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | |
| 798 const base::TimeTicks& start_time) const { | |
| 799 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 800 | |
| 759 // If the device is currently offline, then return | 801 // If the device is currently offline, then return |
| 760 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. | 802 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. |
| 761 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) | 803 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) |
| 762 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; | 804 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; |
| 763 | 805 |
| 764 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); | 806 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); |
| 765 if (!GetRecentHttpRTTMedian(start_time, &http_rtt)) | 807 if (!GetRecentHttpRTTMedian(start_time, &http_rtt)) |
| 766 http_rtt = nqe::internal::InvalidRTT(); | 808 http_rtt = nqe::internal::InvalidRTT(); |
| 767 | 809 |
| 768 int32_t kbps = nqe::internal::kInvalidThroughput; | 810 int32_t kbps = nqe::internal::kInvalidThroughput; |
| 769 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) | 811 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) |
| 770 kbps = nqe::internal::kInvalidThroughput; | 812 kbps = nqe::internal::kInvalidThroughput; |
| 771 | 813 |
| 772 if (http_rtt == nqe::internal::InvalidRTT() && | 814 if (http_rtt == nqe::internal::InvalidRTT() || |
| 773 kbps == nqe::internal::kInvalidThroughput) { | 815 kbps == nqe::internal::kInvalidThroughput) { |
| 774 // Quality of the current network is unknown. | 816 // Quality of the current network is unknown. |
| 775 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 817 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 776 } | 818 } |
| 777 | 819 |
| 778 // Search from the slowest connection type to the fastest to find the | 820 // Search from the slowest connection type to the fastest to find the |
| 779 // EffectiveConnectionType that best matches the current connection's | 821 // EffectiveConnectionType that best matches the current connection's |
| 780 // performance. The match is done by comparing RTT and throughput. | 822 // performance. The match is done by comparing RTT and throughput. |
| 781 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 823 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 782 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | 824 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); |
| (...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1191 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1233 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1192 DCHECK(thread_checker_.CalledOnValidThread()); | 1234 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1193 | 1235 |
| 1194 // TODO(tbansal): Add hysteresis in the notification. | 1236 // TODO(tbansal): Add hysteresis in the notification. |
| 1195 FOR_EACH_OBSERVER( | 1237 FOR_EACH_OBSERVER( |
| 1196 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1238 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1197 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1239 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1198 } | 1240 } |
| 1199 | 1241 |
| 1200 } // namespace net | 1242 } // namespace net |
| OLD | NEW |