Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(863)

Side by Side Diff: net/nqe/network_quality_estimator.cc

Issue 2128793003: Factor out NetworkID and caching mechanism from n_q_e.{h,cc} (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rebased Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm( 247 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm(
248 variation_params)) == algorithm_name_to_enum_.end() 248 variation_params)) == algorithm_name_to_enum_.end()
249 ? kDefaultEffectiveConnectionTypeAlgorithm 249 ? kDefaultEffectiveConnectionTypeAlgorithm
250 : algorithm_name_to_enum_ 250 : algorithm_name_to_enum_
251 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) 251 .find(GetEffectiveConnectionTypeAlgorithm(variation_params))
252 ->second), 252 ->second),
253 tick_clock_(new base::DefaultTickClock()), 253 tick_clock_(new base::DefaultTickClock()),
254 effective_connection_type_recomputation_interval_( 254 effective_connection_type_recomputation_interval_(
255 base::TimeDelta::FromSeconds(15)), 255 base::TimeDelta::FromSeconds(15)),
256 last_connection_change_(tick_clock_->NowTicks()), 256 last_connection_change_(tick_clock_->NowTicks()),
257 current_network_id_( 257 current_network_id_(nqe::internal::NetworkID(
258 NetworkID(NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, 258 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN,
259 std::string())), 259 std::string())),
260 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), 260 downstream_throughput_kbps_observations_(weight_multiplier_per_second_),
261 rtt_observations_(weight_multiplier_per_second_), 261 rtt_observations_(weight_multiplier_per_second_),
262 effective_connection_type_at_last_main_frame_( 262 effective_connection_type_at_last_main_frame_(
263 EFFECTIVE_CONNECTION_TYPE_UNKNOWN), 263 EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
264 external_estimate_provider_(std::move(external_estimates_provider)), 264 external_estimate_provider_(std::move(external_estimates_provider)),
265 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), 265 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN),
266 min_signal_strength_since_connection_change_(INT32_MAX), 266 min_signal_strength_since_connection_change_(INT32_MAX),
267 max_signal_strength_since_connection_change_(INT32_MIN), 267 max_signal_strength_since_connection_change_(INT32_MIN),
268 weak_ptr_factory_(this) { 268 weak_ptr_factory_(this) {
269 static_assert(kDefaultHalfLifeSeconds > 0, 269 static_assert(kDefaultHalfLifeSeconds > 0,
270 "Default half life duration must be > 0"); 270 "Default half life duration must be > 0");
271 static_assert(kMaximumNetworkQualityCacheSize > 0,
272 "Size of the network quality cache must be > 0");
273 // This limit should not be increased unless the logic for removing the
274 // oldest cache entry is rewritten to use a doubly-linked-list LRU queue.
275 static_assert(kMaximumNetworkQualityCacheSize <= 10,
276 "Size of the network quality cache must <= 10");
277 // None of the algorithms can have an empty name. 271 // None of the algorithms can have an empty name.
278 DCHECK(algorithm_name_to_enum_.end() == 272 DCHECK(algorithm_name_to_enum_.end() ==
279 algorithm_name_to_enum_.find(std::string())); 273 algorithm_name_to_enum_.find(std::string()));
280 274
281 DCHECK_EQ(algorithm_name_to_enum_.size(), 275 DCHECK_EQ(algorithm_name_to_enum_.size(),
282 static_cast<size_t>(EffectiveConnectionTypeAlgorithm:: 276 static_cast<size_t>(EffectiveConnectionTypeAlgorithm::
283 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST)); 277 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST));
284 DCHECK_NE(EffectiveConnectionTypeAlgorithm:: 278 DCHECK_NE(EffectiveConnectionTypeAlgorithm::
285 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST, 279 EFFECTIVE_CONNECTION_TYPE_ALGORITHM_LAST,
286 effective_connection_type_algorithm_); 280 effective_connection_type_algorithm_);
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY); 749 EXTERNAL_ESTIMATE_PROVIDER_STATUS_BOUNDARY);
756 } 750 }
757 751
758 void NetworkQualityEstimator::OnConnectionTypeChanged( 752 void NetworkQualityEstimator::OnConnectionTypeChanged(
759 NetworkChangeNotifier::ConnectionType type) { 753 NetworkChangeNotifier::ConnectionType type) {
760 DCHECK(thread_checker_.CalledOnValidThread()); 754 DCHECK(thread_checker_.CalledOnValidThread());
761 755
762 RecordMetricsOnConnectionTypeChanged(); 756 RecordMetricsOnConnectionTypeChanged();
763 757
764 // Write the estimates of the previous network to the cache. 758 // Write the estimates of the previous network to the cache.
765 CacheNetworkQualityEstimate(); 759 network_qualities_manager_.CacheNetworkQualityEstimate(
760 current_network_id_, nqe::internal::CachedNetworkQuality(
761 last_effective_connection_type_computation_,
762 estimated_quality_at_last_main_frame_));
766 763
767 // Clear the local state. 764 // Clear the local state.
768 last_connection_change_ = tick_clock_->NowTicks(); 765 last_connection_change_ = tick_clock_->NowTicks();
769 peak_network_quality_ = nqe::internal::NetworkQuality(); 766 peak_network_quality_ = nqe::internal::NetworkQuality();
770 downstream_throughput_kbps_observations_.Clear(); 767 downstream_throughput_kbps_observations_.Clear();
771 rtt_observations_.Clear(); 768 rtt_observations_.Clear();
772 769
773 #if defined(OS_ANDROID) 770 #if defined(OS_ANDROID)
774 if (NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) { 771 if (NetworkChangeNotifier::IsConnectionCellular(current_network_id_.type)) {
775 UMA_HISTOGRAM_BOOLEAN( 772 UMA_HISTOGRAM_BOOLEAN(
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after
973 NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics( 970 NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics(
974 const base::TimeTicks& start_time, 971 const base::TimeTicks& start_time,
975 NetworkQualityEstimator::MetricUsage http_rtt_metric, 972 NetworkQualityEstimator::MetricUsage http_rtt_metric,
976 NetworkQualityEstimator::MetricUsage transport_rtt_metric, 973 NetworkQualityEstimator::MetricUsage transport_rtt_metric,
977 NetworkQualityEstimator::MetricUsage downstream_throughput_kbps_metric) 974 NetworkQualityEstimator::MetricUsage downstream_throughput_kbps_metric)
978 const { 975 const {
979 DCHECK(thread_checker_.CalledOnValidThread()); 976 DCHECK(thread_checker_.CalledOnValidThread());
980 977
981 // If the device is currently offline, then return 978 // If the device is currently offline, then return
982 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. 979 // EFFECTIVE_CONNECTION_TYPE_OFFLINE.
983 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) 980 if (current_network_id_.type == NetworkChangeNotifier::CONNECTION_NONE)
984 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; 981 return EFFECTIVE_CONNECTION_TYPE_OFFLINE;
985 982
986 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); 983 base::TimeDelta http_rtt = nqe::internal::InvalidRTT();
987 if (http_rtt_metric != NetworkQualityEstimator::MetricUsage::DO_NOT_USE && 984 if (http_rtt_metric != NetworkQualityEstimator::MetricUsage::DO_NOT_USE &&
988 !GetRecentHttpRTTMedian(start_time, &http_rtt)) { 985 !GetRecentHttpRTTMedian(start_time, &http_rtt)) {
989 http_rtt = nqe::internal::InvalidRTT(); 986 http_rtt = nqe::internal::InvalidRTT();
990 } 987 }
991 988
992 base::TimeDelta transport_rtt = nqe::internal::InvalidRTT(); 989 base::TimeDelta transport_rtt = nqe::internal::InvalidRTT();
993 if (transport_rtt_metric != 990 if (transport_rtt_metric !=
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after
1158 // thus a higher percentile throughput will be faster than a lower one. 1155 // thus a higher percentile throughput will be faster than a lower one.
1159 int32_t kbps = nqe::internal::kInvalidThroughput; 1156 int32_t kbps = nqe::internal::kInvalidThroughput;
1160 if (!downstream_throughput_kbps_observations_.GetPercentile( 1157 if (!downstream_throughput_kbps_observations_.GetPercentile(
1161 start_time, &kbps, 100 - percentile, 1158 start_time, &kbps, 100 - percentile,
1162 std::vector<NetworkQualityObservationSource>())) { 1159 std::vector<NetworkQualityObservationSource>())) {
1163 return nqe::internal::kInvalidThroughput; 1160 return nqe::internal::kInvalidThroughput;
1164 } 1161 }
1165 return kbps; 1162 return kbps;
1166 } 1163 }
1167 1164
1168 NetworkQualityEstimator::NetworkID 1165 nqe::internal::NetworkID NetworkQualityEstimator::GetCurrentNetworkID() const {
1169 NetworkQualityEstimator::GetCurrentNetworkID() const {
1170 DCHECK(thread_checker_.CalledOnValidThread()); 1166 DCHECK(thread_checker_.CalledOnValidThread());
1171 1167
1172 // TODO(tbansal): crbug.com/498068 Add NetworkQualityEstimatorAndroid class 1168 // TODO(tbansal): crbug.com/498068 Add NetworkQualityEstimatorAndroid class
1173 // that overrides this method on the Android platform. 1169 // that overrides this method on the Android platform.
1174 1170
1175 // It is possible that the connection type changed between when 1171 // It is possible that the connection type changed between when
1176 // GetConnectionType() was called and when the API to determine the 1172 // GetConnectionType() was called and when the API to determine the
1177 // network name was called. Check if that happened and retry until the 1173 // network name was called. Check if that happened and retry until the
1178 // connection type stabilizes. This is an imperfect solution but should 1174 // connection type stabilizes. This is an imperfect solution but should
1179 // capture majority of cases, and should not significantly affect estimates 1175 // capture majority of cases, and should not significantly affect estimates
1180 // (that are approximate to begin with). 1176 // (that are approximate to begin with).
1181 while (true) { 1177 while (true) {
1182 NetworkQualityEstimator::NetworkID network_id( 1178 nqe::internal::NetworkID network_id(
1183 NetworkChangeNotifier::GetConnectionType(), std::string()); 1179 NetworkChangeNotifier::GetConnectionType(), std::string());
1184 1180
1185 switch (network_id.type) { 1181 switch (network_id.type) {
1186 case NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN: 1182 case NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN:
1187 case NetworkChangeNotifier::ConnectionType::CONNECTION_NONE: 1183 case NetworkChangeNotifier::ConnectionType::CONNECTION_NONE:
1188 case NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH: 1184 case NetworkChangeNotifier::ConnectionType::CONNECTION_BLUETOOTH:
1189 case NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET: 1185 case NetworkChangeNotifier::ConnectionType::CONNECTION_ETHERNET:
1190 break; 1186 break;
1191 case NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI: 1187 case NetworkChangeNotifier::ConnectionType::CONNECTION_WIFI:
1192 #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \ 1188 #if defined(OS_ANDROID) || defined(OS_LINUX) || defined(OS_CHROMEOS) || \
(...skipping 15 matching lines...) Expand all
1208 1204
1209 if (network_id.type == NetworkChangeNotifier::GetConnectionType()) 1205 if (network_id.type == NetworkChangeNotifier::GetConnectionType())
1210 return network_id; 1206 return network_id;
1211 } 1207 }
1212 NOTREACHED(); 1208 NOTREACHED();
1213 } 1209 }
1214 1210
1215 bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() { 1211 bool NetworkQualityEstimator::ReadCachedNetworkQualityEstimate() {
1216 DCHECK(thread_checker_.CalledOnValidThread()); 1212 DCHECK(thread_checker_.CalledOnValidThread());
1217 1213
1218 // If the network name is unavailable, caching should not be performed. 1214 nqe::internal::CachedNetworkQuality cached_network_quality;
1219 if (current_network_id_.id.empty()) 1215
1216 if (!network_qualities_manager_.GetCachedNetworkQualityEstimate(
1217 current_network_id_, &cached_network_quality)) {
1218 UMA_HISTOGRAM_BOOLEAN("NQE.CachedNetworkQualityAvailable", false);
RyanSturm 2016/07/12 18:45:38 Can you combine the two NQE.CacheNetworkQualityAva
tbansal1 2016/07/12 19:40:19 Done.
1220 return false; 1219 return false;
1221 1220 }
1222 CachedNetworkQualities::const_iterator it =
1223 cached_network_qualities_.find(current_network_id_);
1224
1225 if (it == cached_network_qualities_.end())
1226 return false;
1227
1228 nqe::internal::NetworkQuality network_quality(it->second.network_quality());
1229 1221
1230 const base::TimeTicks now = tick_clock_->NowTicks(); 1222 const base::TimeTicks now = tick_clock_->NowTicks();
1231 bool read_cached_estimate = false;
1232 1223
1233 if (network_quality.downstream_throughput_kbps() != 1224 if (cached_network_quality.network_quality().downstream_throughput_kbps() !=
1234 nqe::internal::kInvalidThroughput) { 1225 nqe::internal::kInvalidThroughput) {
1235 read_cached_estimate = true;
1236 ThroughputObservation througphput_observation( 1226 ThroughputObservation througphput_observation(
1237 network_quality.downstream_throughput_kbps(), now, 1227 cached_network_quality.network_quality().downstream_throughput_kbps(),
1238 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE); 1228 now, NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE);
1239 downstream_throughput_kbps_observations_.AddObservation( 1229 downstream_throughput_kbps_observations_.AddObservation(
1240 througphput_observation); 1230 througphput_observation);
1241 NotifyObserversOfThroughput(througphput_observation); 1231 NotifyObserversOfThroughput(througphput_observation);
1242 } 1232 }
1243 1233
1244 if (network_quality.http_rtt() != nqe::internal::InvalidRTT()) { 1234 if (cached_network_quality.network_quality().http_rtt() !=
1245 read_cached_estimate = true; 1235 nqe::internal::InvalidRTT()) {
1246 RttObservation rtt_observation( 1236 RttObservation rtt_observation(
1247 network_quality.http_rtt(), now, 1237 cached_network_quality.network_quality().http_rtt(), now,
1248 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE); 1238 NETWORK_QUALITY_OBSERVATION_SOURCE_CACHED_ESTIMATE);
1249 rtt_observations_.AddObservation(rtt_observation); 1239 rtt_observations_.AddObservation(rtt_observation);
1250 NotifyObserversOfRTT(rtt_observation); 1240 NotifyObserversOfRTT(rtt_observation);
1251 } 1241 }
1252 1242 UMA_HISTOGRAM_BOOLEAN("NQE.CachedNetworkQualityAvailable", true);
1253 return read_cached_estimate; 1243 return true;
1254 } 1244 }
1255 1245
1256 void NetworkQualityEstimator::OnUpdatedEstimateAvailable( 1246 void NetworkQualityEstimator::OnUpdatedEstimateAvailable(
1257 const base::TimeDelta& rtt, 1247 const base::TimeDelta& rtt,
1258 int32_t downstream_throughput_kbps, 1248 int32_t downstream_throughput_kbps,
1259 int32_t upstream_throughput_kbps) { 1249 int32_t upstream_throughput_kbps) {
1260 DCHECK(thread_checker_.CalledOnValidThread()); 1250 DCHECK(thread_checker_.CalledOnValidThread());
1261 DCHECK(external_estimate_provider_); 1251 DCHECK(external_estimate_provider_);
1262 1252
1263 RecordExternalEstimateProviderMetrics( 1253 RecordExternalEstimateProviderMetrics(
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 NOTREACHED(); 1320 NOTREACHED();
1331 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; 1321 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN;
1332 } 1322 }
1333 1323
1334 void NetworkQualityEstimator::SetTickClockForTesting( 1324 void NetworkQualityEstimator::SetTickClockForTesting(
1335 std::unique_ptr<base::TickClock> tick_clock) { 1325 std::unique_ptr<base::TickClock> tick_clock) {
1336 DCHECK(thread_checker_.CalledOnValidThread()); 1326 DCHECK(thread_checker_.CalledOnValidThread());
1337 tick_clock_ = std::move(tick_clock); 1327 tick_clock_ = std::move(tick_clock);
1338 } 1328 }
1339 1329
1340 void NetworkQualityEstimator::CacheNetworkQualityEstimate() {
1341 DCHECK(thread_checker_.CalledOnValidThread());
1342 DCHECK_LE(cached_network_qualities_.size(),
1343 static_cast<size_t>(kMaximumNetworkQualityCacheSize));
1344
1345 // If the network name is unavailable, caching should not be performed.
1346 if (current_network_id_.id.empty())
1347 return;
1348
1349 base::TimeDelta http_rtt = nqe::internal::InvalidRTT();
1350 int32_t downlink_throughput_kbps = nqe::internal::kInvalidThroughput;
1351
1352 if (!GetHttpRTTEstimate(&http_rtt) ||
1353 !GetDownlinkThroughputKbpsEstimate(&downlink_throughput_kbps)) {
1354 return;
1355 }
1356
1357 // |transport_rtt| is currently not cached.
1358 nqe::internal::NetworkQuality network_quality = nqe::internal::NetworkQuality(
1359 http_rtt, nqe::internal::InvalidRTT() /* transport_rtt */,
1360 downlink_throughput_kbps);
1361
1362 if (cached_network_qualities_.size() == kMaximumNetworkQualityCacheSize) {
1363 // Remove the oldest entry.
1364 CachedNetworkQualities::iterator oldest_entry_iterator =
1365 cached_network_qualities_.begin();
1366
1367 for (CachedNetworkQualities::iterator it =
1368 cached_network_qualities_.begin();
1369 it != cached_network_qualities_.end(); ++it) {
1370 if ((it->second).OlderThan(oldest_entry_iterator->second))
1371 oldest_entry_iterator = it;
1372 }
1373 cached_network_qualities_.erase(oldest_entry_iterator);
1374 }
1375 DCHECK_LT(cached_network_qualities_.size(),
1376 static_cast<size_t>(kMaximumNetworkQualityCacheSize));
1377
1378 cached_network_qualities_.insert(
1379 std::make_pair(current_network_id_,
1380 nqe::internal::CachedNetworkQuality(network_quality)));
1381 DCHECK_LE(cached_network_qualities_.size(),
1382 static_cast<size_t>(kMaximumNetworkQualityCacheSize));
1383 }
1384
1385 void NetworkQualityEstimator::OnUpdatedRTTAvailable( 1330 void NetworkQualityEstimator::OnUpdatedRTTAvailable(
1386 SocketPerformanceWatcherFactory::Protocol protocol, 1331 SocketPerformanceWatcherFactory::Protocol protocol,
1387 const base::TimeDelta& rtt) { 1332 const base::TimeDelta& rtt) {
1388 DCHECK(thread_checker_.CalledOnValidThread()); 1333 DCHECK(thread_checker_.CalledOnValidThread());
1389 DCHECK_NE(nqe::internal::InvalidRTT(), rtt); 1334 DCHECK_NE(nqe::internal::InvalidRTT(), rtt);
1390 1335
1391 RttObservation observation(rtt, tick_clock_->NowTicks(), 1336 RttObservation observation(rtt, tick_clock_->NowTicks(),
1392 ProtocolSourceToObservationSource(protocol)); 1337 ProtocolSourceToObservationSource(protocol));
1393 NotifyObserversOfRTT(observation); 1338 NotifyObserversOfRTT(observation);
1394 rtt_observations_.AddObservation(observation); 1339 rtt_observations_.AddObservation(observation);
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
1472 NotifyObserversOfEffectiveConnectionTypeChanged() { 1417 NotifyObserversOfEffectiveConnectionTypeChanged() {
1473 DCHECK(thread_checker_.CalledOnValidThread()); 1418 DCHECK(thread_checker_.CalledOnValidThread());
1474 1419
1475 // TODO(tbansal): Add hysteresis in the notification. 1420 // TODO(tbansal): Add hysteresis in the notification.
1476 FOR_EACH_OBSERVER( 1421 FOR_EACH_OBSERVER(
1477 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, 1422 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_,
1478 OnEffectiveConnectionTypeChanged(effective_connection_type_)); 1423 OnEffectiveConnectionTypeChanged(effective_connection_type_));
1479 } 1424 }
1480 1425
1481 } // namespace net 1426 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698