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 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 133 DCHECK_GT(max_limit, kLowerLimit); | 133 DCHECK_GT(max_limit, kLowerLimit); |
| 134 const size_t kBucketCount = 50; | 134 const size_t kBucketCount = 50; |
| 135 | 135 |
| 136 // Prefix of network quality estimator histograms. | 136 // Prefix of network quality estimator histograms. |
| 137 const char prefix[] = "NQE."; | 137 const char prefix[] = "NQE."; |
| 138 return base::Histogram::FactoryGet( | 138 return base::Histogram::FactoryGet( |
| 139 prefix + statistic_name + GetNameForConnectionType(type), kLowerLimit, | 139 prefix + statistic_name + GetNameForConnectionType(type), kLowerLimit, |
| 140 max_limit, kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag); | 140 max_limit, kBucketCount, base::HistogramBase::kUmaTargetedHistogramFlag); |
| 141 } | 141 } |
| 142 | 142 |
| 143 bool GetValueForVariationParam( | 143 // Sets |variations_value| to the value of |parameter_name| read from |
| 144 // |variation_params|. If the value is unavailable from |variation_params|, then | |
| 145 // |variations_value| is set to |default_value|. | |
| 146 void GetValueForVariationParam( | |
| 144 const std::map<std::string, std::string>& variation_params, | 147 const std::map<std::string, std::string>& variation_params, |
| 145 const std::string& parameter_name, | 148 const std::string& parameter_name, |
| 149 int32_t default_value, | |
| 146 int32_t* variations_value) { | 150 int32_t* variations_value) { |
| 147 const auto it = variation_params.find(parameter_name); | 151 const auto it = variation_params.find(parameter_name); |
| 148 return it != variation_params.end() && | 152 if (it != variation_params.end() && |
| 149 base::StringToInt(it->second, variations_value); | 153 base::StringToInt(it->second, variations_value)) { |
| 154 return; | |
| 155 } | |
| 156 *variations_value = default_value; | |
| 150 } | 157 } |
| 151 | 158 |
| 152 // Returns the algorithm that should be used for computing effective connection | 159 // Returns the algorithm that should be used for computing effective connection |
| 153 // type based on field trial params. Returns an empty string if a valid | 160 // type based on field trial params. Returns an empty string if a valid |
| 154 // algorithm paramter is not present in the field trial params. | 161 // algorithm paramter is not present in the field trial params. |
| 155 std::string GetEffectiveConnectionTypeAlgorithm( | 162 std::string GetEffectiveConnectionTypeAlgorithm( |
| 156 const std::map<std::string, std::string>& variation_params) { | 163 const std::map<std::string, std::string>& variation_params) { |
| 157 const auto it = variation_params.find("effective_connection_type_algorithm"); | 164 const auto it = variation_params.find("effective_connection_type_algorithm"); |
| 158 if (it == variation_params.end()) | 165 if (it == variation_params.end()) |
| 159 return std::string(); | 166 return std::string(); |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 base::ThreadTaskRunnerHandle::Get(), | 316 base::ThreadTaskRunnerHandle::Get(), |
| 310 base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable, | 317 base::Bind(&NetworkQualityEstimator::OnUpdatedRTTAvailable, |
| 311 base::Unretained(this)))); | 318 base::Unretained(this)))); |
| 312 | 319 |
| 313 // Record accuracy at 3 different intervals. The values used here must remain | 320 // Record accuracy at 3 different intervals. The values used here must remain |
| 314 // in sync with the suffixes specified in | 321 // in sync with the suffixes specified in |
| 315 // tools/metrics/histograms/histograms.xml. | 322 // tools/metrics/histograms/histograms.xml. |
| 316 accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(15)); | 323 accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(15)); |
| 317 accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(30)); | 324 accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(30)); |
| 318 accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(60)); | 325 accuracy_recording_intervals_.push_back(base::TimeDelta::FromSeconds(60)); |
| 326 | |
| 327 // Below 33rd percentile of 2G transport RTT observations. | |
| 328 default_connection_thresholds_[EFFECTIVE_CONNECTION_TYPE_SLOW_2G] = | |
| 329 nqe::internal::NetworkQuality(nqe::internal::InvalidRTT(), | |
| 330 base::TimeDelta::FromMilliseconds(1870), | |
|
RyanSturm
2016/07/12 19:57:55
nit: Can you move the 1870 and 1300 to a static co
tbansal1
2016/07/12 20:32:25
I would prefer to keep them here instead of using
RyanSturm
2016/07/12 20:44:47
I think it would be more clear like:
// 1.87 seco
tbansal1
2016/07/13 05:52:03
I updated the comments.
| |
| 331 nqe::internal::kInvalidThroughput); | |
| 332 | |
| 333 // 50th percentile of 2G transport RTT observations. | |
| 334 default_connection_thresholds_[EFFECTIVE_CONNECTION_TYPE_2G] = | |
| 335 nqe::internal::NetworkQuality(nqe::internal::InvalidRTT(), | |
| 336 base::TimeDelta::FromMilliseconds(1300), | |
| 337 nqe::internal::kInvalidThroughput); | |
| 319 } | 338 } |
| 320 | 339 |
| 321 void NetworkQualityEstimator::ObtainOperatingParams( | 340 void NetworkQualityEstimator::ObtainOperatingParams( |
| 322 const std::map<std::string, std::string>& variation_params) { | 341 const std::map<std::string, std::string>& variation_params) { |
| 323 DCHECK(thread_checker_.CalledOnValidThread()); | 342 DCHECK(thread_checker_.CalledOnValidThread()); |
| 324 | 343 |
| 325 for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) { | 344 for (size_t i = 0; i <= NetworkChangeNotifier::CONNECTION_LAST; ++i) { |
| 326 NetworkChangeNotifier::ConnectionType type = | 345 NetworkChangeNotifier::ConnectionType type = |
| 327 static_cast<NetworkChangeNotifier::ConnectionType>(i); | 346 static_cast<NetworkChangeNotifier::ConnectionType>(i); |
| 328 DCHECK_EQ(nqe::internal::InvalidRTT(), default_observations_[i].http_rtt()); | 347 DCHECK_EQ(nqe::internal::InvalidRTT(), default_observations_[i].http_rtt()); |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 374 DCHECK_EQ(nqe::internal::InvalidRTT(), | 393 DCHECK_EQ(nqe::internal::InvalidRTT(), |
| 375 connection_thresholds_[i].transport_rtt()); | 394 connection_thresholds_[i].transport_rtt()); |
| 376 DCHECK_EQ(nqe::internal::kInvalidThroughput, | 395 DCHECK_EQ(nqe::internal::kInvalidThroughput, |
| 377 connection_thresholds_[i].downstream_throughput_kbps()); | 396 connection_thresholds_[i].downstream_throughput_kbps()); |
| 378 if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | 397 if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
| 379 continue; | 398 continue; |
| 380 | 399 |
| 381 std::string connection_type_name = std::string( | 400 std::string connection_type_name = std::string( |
| 382 GetNameForEffectiveConnectionType(effective_connection_type)); | 401 GetNameForEffectiveConnectionType(effective_connection_type)); |
| 383 | 402 |
| 384 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; | 403 int32_t variations_value; |
| 385 if (GetValueForVariationParam( | 404 GetValueForVariationParam( |
| 386 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, | 405 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, |
| 387 &variations_value) && | 406 default_connection_thresholds_[i].http_rtt().InMilliseconds(), |
| 388 variations_value >= kMinimumRTTVariationParameterMsec) { | 407 &variations_value); |
| 389 connection_thresholds_[i].set_http_rtt( | 408 connection_thresholds_[i].set_http_rtt( |
| 390 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); | 409 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); |
| 410 // Verify that the RTT values are in decreasing order as the network | |
| 411 // quality improves. | |
| 412 DCHECK(i == 0 || | |
| 413 connection_thresholds_[i].http_rtt() == | |
| 414 nqe::internal::InvalidRTT() || | |
| 415 connection_thresholds_[i - 1].http_rtt() == | |
| 416 nqe::internal::InvalidRTT() || | |
| 417 connection_thresholds_[i].http_rtt() <= | |
| 418 connection_thresholds_[i - 1].http_rtt()); | |
| 391 | 419 |
| 392 // Verify that the RTT values are in decreasing order as the network | 420 GetValueForVariationParam( |
| 393 // quality improves. | 421 variation_params, |
| 394 DCHECK(i == 0 || | 422 connection_type_name + kThresholdTransportRTTMsecSuffix, |
| 395 connection_thresholds_[i - 1].http_rtt() == | 423 default_connection_thresholds_[i].transport_rtt().InMilliseconds(), |
| 396 nqe::internal::InvalidRTT() || | 424 &variations_value); |
| 397 connection_thresholds_[i].http_rtt() <= | 425 connection_thresholds_[i].set_transport_rtt( |
| 398 connection_thresholds_[i - 1].http_rtt()); | 426 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); |
| 399 } | 427 // Verify that the transport RTT values are in decreasing order as the |
| 428 // network quality improves. | |
| 429 DCHECK(i == 0 || | |
| 430 connection_thresholds_[i].transport_rtt() == | |
| 431 nqe::internal::InvalidRTT() || | |
| 432 connection_thresholds_[i - 1].transport_rtt() == | |
| 433 nqe::internal::InvalidRTT() || | |
| 434 connection_thresholds_[i].transport_rtt() <= | |
| 435 connection_thresholds_[i - 1].transport_rtt()); | |
| 400 | 436 |
| 401 variations_value = kMinimumRTTVariationParameterMsec - 1; | 437 GetValueForVariationParam( |
| 402 if (GetValueForVariationParam( | 438 variation_params, connection_type_name + kThresholdKbpsSuffix, |
| 403 variation_params, | 439 default_connection_thresholds_[i].downstream_throughput_kbps(), |
| 404 connection_type_name + kThresholdTransportRTTMsecSuffix, | 440 &variations_value); |
| 405 &variations_value) && | 441 connection_thresholds_[i].set_downstream_throughput_kbps(variations_value); |
| 406 variations_value >= kMinimumRTTVariationParameterMsec) { | 442 // Verify that the throughput values are in increasing order as the |
| 407 connection_thresholds_[i].set_transport_rtt( | 443 // network quality improves. |
| 408 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); | 444 DCHECK(i == 0 || |
| 409 | 445 connection_thresholds_[i].downstream_throughput_kbps() == |
| 410 // Verify that the transport RTT values are in decreasing order as the | 446 kMinimumThroughputVariationParameterKbps || |
| 411 // network quality improves. | 447 connection_thresholds_[i - 1].downstream_throughput_kbps() == |
| 412 DCHECK(i == 0 || | 448 kMinimumThroughputVariationParameterKbps || |
| 413 connection_thresholds_[i - 1].transport_rtt() == | 449 connection_thresholds_[i].downstream_throughput_kbps() >= |
| 414 nqe::internal::InvalidRTT() || | 450 connection_thresholds_[i - 1].downstream_throughput_kbps()); |
| 415 connection_thresholds_[i].transport_rtt() <= | |
| 416 connection_thresholds_[i - 1].transport_rtt()); | |
| 417 } | |
| 418 | |
| 419 variations_value = kMinimumThroughputVariationParameterKbps - 1; | |
| 420 if (GetValueForVariationParam(variation_params, | |
| 421 connection_type_name + kThresholdKbpsSuffix, | |
| 422 &variations_value) && | |
| 423 variations_value >= kMinimumThroughputVariationParameterKbps) { | |
| 424 connection_thresholds_[i].set_downstream_throughput_kbps( | |
| 425 variations_value); | |
| 426 | |
| 427 // Verify that the throughput values are in increasing order as the | |
| 428 // network quality improves. | |
| 429 DCHECK(i == 0 || | |
| 430 connection_thresholds_[i - 1].downstream_throughput_kbps() == | |
| 431 kMinimumThroughputVariationParameterKbps || | |
| 432 connection_thresholds_[i].downstream_throughput_kbps() >= | |
| 433 connection_thresholds_[i - 1].downstream_throughput_kbps()); | |
| 434 } | |
| 435 } | 451 } |
| 436 } | 452 } |
| 437 | 453 |
| 438 void NetworkQualityEstimator::AddDefaultEstimates() { | 454 void NetworkQualityEstimator::AddDefaultEstimates() { |
| 439 DCHECK(thread_checker_.CalledOnValidThread()); | 455 DCHECK(thread_checker_.CalledOnValidThread()); |
| 440 | 456 |
| 441 if (default_observations_[current_network_id_.type].http_rtt() != | 457 if (default_observations_[current_network_id_.type].http_rtt() != |
| 442 nqe::internal::InvalidRTT()) { | 458 nqe::internal::InvalidRTT()) { |
| 443 RttObservation rtt_observation( | 459 RttObservation rtt_observation( |
| 444 default_observations_[current_network_id_.type].http_rtt(), | 460 default_observations_[current_network_id_.type].http_rtt(), |
| (...skipping 1001 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1446 | 1462 |
| 1447 void NetworkQualityEstimator::MaybeRecomputeEffectiveConnectionType() { | 1463 void NetworkQualityEstimator::MaybeRecomputeEffectiveConnectionType() { |
| 1448 DCHECK(thread_checker_.CalledOnValidThread()); | 1464 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1449 | 1465 |
| 1450 const base::TimeTicks now = tick_clock_->NowTicks(); | 1466 const base::TimeTicks now = tick_clock_->NowTicks(); |
| 1451 // Recompute effective connection type only if | 1467 // Recompute effective connection type only if |
| 1452 // |effective_connection_type_recomputation_interval_| has passed since it was | 1468 // |effective_connection_type_recomputation_interval_| has passed since it was |
| 1453 // last computed or a connection change event was observed since the last | 1469 // last computed or a connection change event was observed since the last |
| 1454 // computation. Strict inequalities are used to ensure that effective | 1470 // computation. Strict inequalities are used to ensure that effective |
| 1455 // connection type is recomputed on connection change events even if the clock | 1471 // connection type is recomputed on connection change events even if the clock |
| 1456 // has not updated. | 1472 // has not updated. If the algorithm uses transport RTT, then recompute the |
| 1473 // effective connection type if the effective connection type was previously | |
| 1474 // unavailable. This is because the transport RTT observations are voluminous, | |
| 1475 // so it may now be possible to compute the effective connection type. | |
| 1457 if (now - last_effective_connection_type_computation_ < | 1476 if (now - last_effective_connection_type_computation_ < |
| 1458 effective_connection_type_recomputation_interval_ && | 1477 effective_connection_type_recomputation_interval_ && |
| 1459 last_connection_change_ < last_effective_connection_type_computation_) { | 1478 last_connection_change_ < last_effective_connection_type_computation_ && |
| 1479 (effective_connection_type_ != | |
| 1480 NetworkQualityEstimator::EFFECTIVE_CONNECTION_TYPE_UNKNOWN || | |
| 1481 effective_connection_type_algorithm_ != | |
| 1482 EffectiveConnectionTypeAlgorithm:: | |
| 1483 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT)) { | |
| 1460 return; | 1484 return; |
| 1461 } | 1485 } |
| 1462 | 1486 |
| 1463 const EffectiveConnectionType past_type = effective_connection_type_; | 1487 const EffectiveConnectionType past_type = effective_connection_type_; |
| 1464 last_effective_connection_type_computation_ = now; | 1488 last_effective_connection_type_computation_ = now; |
| 1465 effective_connection_type_ = GetEffectiveConnectionType(); | 1489 effective_connection_type_ = GetEffectiveConnectionType(); |
| 1466 | 1490 |
| 1467 if (past_type != effective_connection_type_) | 1491 if (past_type != effective_connection_type_) |
| 1468 NotifyObserversOfEffectiveConnectionTypeChanged(); | 1492 NotifyObserversOfEffectiveConnectionTypeChanged(); |
| 1469 } | 1493 } |
| 1470 | 1494 |
| 1471 void NetworkQualityEstimator:: | 1495 void NetworkQualityEstimator:: |
| 1472 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1496 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1473 DCHECK(thread_checker_.CalledOnValidThread()); | 1497 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1474 | 1498 |
| 1475 // TODO(tbansal): Add hysteresis in the notification. | 1499 // TODO(tbansal): Add hysteresis in the notification. |
| 1476 FOR_EACH_OBSERVER( | 1500 FOR_EACH_OBSERVER( |
| 1477 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1501 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1478 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1502 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1479 } | 1503 } |
| 1480 | 1504 |
| 1481 } // namespace net | 1505 } // namespace net |
| OLD | NEW |