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 368 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 last_connection_change_(tick_clock_->NowTicks()), | 379 last_connection_change_(tick_clock_->NowTicks()), |
380 current_network_id_(nqe::internal::NetworkID( | 380 current_network_id_(nqe::internal::NetworkID( |
381 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, | 381 NetworkChangeNotifier::ConnectionType::CONNECTION_UNKNOWN, |
382 std::string())), | 382 std::string())), |
383 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), | 383 downstream_throughput_kbps_observations_(weight_multiplier_per_second_), |
384 rtt_observations_(weight_multiplier_per_second_), | 384 rtt_observations_(weight_multiplier_per_second_), |
385 effective_connection_type_at_last_main_frame_( | 385 effective_connection_type_at_last_main_frame_( |
386 EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 386 EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
387 external_estimate_provider_(std::move(external_estimates_provider)), | 387 external_estimate_provider_(std::move(external_estimates_provider)), |
388 effective_connection_type_recomputation_interval_( | 388 effective_connection_type_recomputation_interval_( |
389 base::TimeDelta::FromSeconds(15)), | 389 base::TimeDelta::FromSeconds(10)), |
390 rtt_observations_size_at_last_ect_computation_(0), | 390 rtt_observations_size_at_last_ect_computation_(0), |
391 throughput_observations_size_at_last_ect_computation_(0), | 391 throughput_observations_size_at_last_ect_computation_(0), |
392 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), | 392 effective_connection_type_(EFFECTIVE_CONNECTION_TYPE_UNKNOWN), |
393 min_signal_strength_since_connection_change_(INT32_MAX), | 393 min_signal_strength_since_connection_change_(INT32_MAX), |
394 max_signal_strength_since_connection_change_(INT32_MIN), | 394 max_signal_strength_since_connection_change_(INT32_MIN), |
395 correlation_uma_logging_probability_( | 395 correlation_uma_logging_probability_( |
396 GetDoubleValueForVariationParamWithDefaultValue( | 396 GetDoubleValueForVariationParamWithDefaultValue( |
397 variation_params, | 397 variation_params, |
398 "correlation_logging_probability", | 398 "correlation_logging_probability", |
399 0.0)), | 399 0.0)), |
(...skipping 254 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
654 if (!GetTransportRTT(&estimated_transport_rtt)) | 654 if (!GetTransportRTT(&estimated_transport_rtt)) |
655 estimated_transport_rtt = nqe::internal::InvalidRTT(); | 655 estimated_transport_rtt = nqe::internal::InvalidRTT(); |
656 | 656 |
657 int32_t downstream_throughput_kbps; | 657 int32_t downstream_throughput_kbps; |
658 if (!GetDownlinkThroughputKbps(&downstream_throughput_kbps)) | 658 if (!GetDownlinkThroughputKbps(&downstream_throughput_kbps)) |
659 downstream_throughput_kbps = nqe::internal::kInvalidThroughput; | 659 downstream_throughput_kbps = nqe::internal::kInvalidThroughput; |
660 | 660 |
661 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality( | 661 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality( |
662 estimated_http_rtt, estimated_transport_rtt, | 662 estimated_http_rtt, estimated_transport_rtt, |
663 downstream_throughput_kbps); | 663 downstream_throughput_kbps); |
| 664 |
| 665 ComputeEffectiveConnectionType(); |
664 effective_connection_type_at_last_main_frame_ = | 666 effective_connection_type_at_last_main_frame_ = |
665 GetEffectiveConnectionType(); | 667 GetEffectiveConnectionType(); |
666 | 668 |
667 RecordMetricsOnMainFrameRequest(); | 669 RecordMetricsOnMainFrameRequest(); |
668 MaybeQueryExternalEstimateProvider(); | 670 MaybeQueryExternalEstimateProvider(); |
669 | 671 |
670 // Post the tasks which will run in the future and record the estimation | 672 // Post the tasks which will run in the future and record the estimation |
671 // accuracy based on the observations received between now and the time of | 673 // accuracy based on the observations received between now and the time of |
672 // task execution. Posting the task at different intervals makes it | 674 // task execution. Posting the task at different intervals makes it |
673 // possible to measure the accuracy by comparing the estimate with the | 675 // possible to measure the accuracy by comparing the estimate with the |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1029 RecordNetworkIDAvailability(); | 1031 RecordNetworkIDAvailability(); |
1030 | 1032 |
1031 MaybeQueryExternalEstimateProvider(); | 1033 MaybeQueryExternalEstimateProvider(); |
1032 | 1034 |
1033 // Read any cached estimates for the new network. If cached estimates are | 1035 // Read any cached estimates for the new network. If cached estimates are |
1034 // unavailable, add the default estimates. | 1036 // unavailable, add the default estimates. |
1035 if (!ReadCachedNetworkQualityEstimate()) | 1037 if (!ReadCachedNetworkQualityEstimate()) |
1036 AddDefaultEstimates(); | 1038 AddDefaultEstimates(); |
1037 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); | 1039 estimated_quality_at_last_main_frame_ = nqe::internal::NetworkQuality(); |
1038 throughput_analyzer_->OnConnectionTypeChanged(); | 1040 throughput_analyzer_->OnConnectionTypeChanged(); |
1039 MaybeRecomputeEffectiveConnectionType(); | 1041 MaybeComputeEffectiveConnectionType(); |
1040 UpdateSignalStrength(); | 1042 UpdateSignalStrength(); |
1041 } | 1043 } |
1042 | 1044 |
1043 void NetworkQualityEstimator::MaybeQueryExternalEstimateProvider() const { | 1045 void NetworkQualityEstimator::MaybeQueryExternalEstimateProvider() const { |
1044 // Query the external estimate provider on certain connection types. Once the | 1046 // Query the external estimate provider on certain connection types. Once the |
1045 // updated estimates are available, OnUpdatedEstimateAvailable will be called | 1047 // updated estimates are available, OnUpdatedEstimateAvailable will be called |
1046 // by |external_estimate_provider_| with updated estimates. | 1048 // by |external_estimate_provider_| with updated estimates. |
1047 if (external_estimate_provider_ && | 1049 if (external_estimate_provider_ && |
1048 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && | 1050 current_network_id_.type != NetworkChangeNotifier::CONNECTION_NONE && |
1049 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && | 1051 current_network_id_.type != NetworkChangeNotifier::CONNECTION_UNKNOWN && |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1184 base::Histogram::FactoryGet( | 1186 base::Histogram::FactoryGet( |
1185 std::string("NQE.MainFrame.EffectiveConnectionType.") + | 1187 std::string("NQE.MainFrame.EffectiveConnectionType.") + |
1186 GetNameForConnectionType(current_network_id_.type), | 1188 GetNameForConnectionType(current_network_id_.type), |
1187 0, EFFECTIVE_CONNECTION_TYPE_LAST, | 1189 0, EFFECTIVE_CONNECTION_TYPE_LAST, |
1188 EFFECTIVE_CONNECTION_TYPE_LAST /* Number of buckets */, | 1190 EFFECTIVE_CONNECTION_TYPE_LAST /* Number of buckets */, |
1189 base::HistogramBase::kUmaTargetedHistogramFlag); | 1191 base::HistogramBase::kUmaTargetedHistogramFlag); |
1190 | 1192 |
1191 effective_connection_type_histogram->Add(effective_connection_type); | 1193 effective_connection_type_histogram->Add(effective_connection_type); |
1192 } | 1194 } |
1193 | 1195 |
| 1196 void NetworkQualityEstimator::ComputeEffectiveConnectionType() { |
| 1197 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1198 |
| 1199 const base::TimeTicks now = tick_clock_->NowTicks(); |
| 1200 |
| 1201 const EffectiveConnectionType past_type = effective_connection_type_; |
| 1202 last_effective_connection_type_computation_ = now; |
| 1203 |
| 1204 effective_connection_type_ = |
| 1205 GetRecentEffectiveConnectionType(base::TimeTicks()); |
| 1206 |
| 1207 if (past_type != effective_connection_type_) |
| 1208 NotifyObserversOfEffectiveConnectionTypeChanged(); |
| 1209 |
| 1210 rtt_observations_size_at_last_ect_computation_ = rtt_observations_.Size(); |
| 1211 throughput_observations_size_at_last_ect_computation_ = |
| 1212 downstream_throughput_kbps_observations_.Size(); |
| 1213 } |
| 1214 |
1194 EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType() | 1215 EffectiveConnectionType NetworkQualityEstimator::GetEffectiveConnectionType() |
1195 const { | 1216 const { |
1196 DCHECK(thread_checker_.CalledOnValidThread()); | 1217 DCHECK(thread_checker_.CalledOnValidThread()); |
1197 return GetRecentEffectiveConnectionType(base::TimeTicks()); | 1218 return effective_connection_type_; |
1198 } | 1219 } |
1199 | 1220 |
1200 EffectiveConnectionType | 1221 EffectiveConnectionType |
1201 NetworkQualityEstimator::GetRecentEffectiveConnectionType( | 1222 NetworkQualityEstimator::GetRecentEffectiveConnectionType( |
1202 const base::TimeTicks& start_time) const { | 1223 const base::TimeTicks& start_time) const { |
1203 DCHECK(thread_checker_.CalledOnValidThread()); | 1224 DCHECK(thread_checker_.CalledOnValidThread()); |
1204 | 1225 |
1205 if (effective_connection_type_algorithm_ == | 1226 if (effective_connection_type_algorithm_ == |
1206 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { | 1227 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { |
1207 return GetRecentEffectiveConnectionTypeUsingMetrics( | 1228 return GetRecentEffectiveConnectionTypeUsingMetrics( |
(...skipping 390 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1598 rtt_observations_.AddObservation(observation); | 1619 rtt_observations_.AddObservation(observation); |
1599 } | 1620 } |
1600 | 1621 |
1601 void NetworkQualityEstimator::NotifyObserversOfRTT( | 1622 void NetworkQualityEstimator::NotifyObserversOfRTT( |
1602 const RttObservation& observation) { | 1623 const RttObservation& observation) { |
1603 DCHECK(thread_checker_.CalledOnValidThread()); | 1624 DCHECK(thread_checker_.CalledOnValidThread()); |
1604 DCHECK_NE(nqe::internal::InvalidRTT(), observation.value); | 1625 DCHECK_NE(nqe::internal::InvalidRTT(), observation.value); |
1605 | 1626 |
1606 // Maybe recompute the effective connection type since a new RTT observation | 1627 // Maybe recompute the effective connection type since a new RTT observation |
1607 // is available. | 1628 // is available. |
1608 MaybeRecomputeEffectiveConnectionType(); | 1629 MaybeComputeEffectiveConnectionType(); |
1609 FOR_EACH_OBSERVER( | 1630 FOR_EACH_OBSERVER( |
1610 RTTObserver, rtt_observer_list_, | 1631 RTTObserver, rtt_observer_list_, |
1611 OnRTTObservation(observation.value.InMilliseconds(), | 1632 OnRTTObservation(observation.value.InMilliseconds(), |
1612 observation.timestamp, observation.source)); | 1633 observation.timestamp, observation.source)); |
1613 } | 1634 } |
1614 | 1635 |
1615 void NetworkQualityEstimator::NotifyObserversOfThroughput( | 1636 void NetworkQualityEstimator::NotifyObserversOfThroughput( |
1616 const ThroughputObservation& observation) { | 1637 const ThroughputObservation& observation) { |
1617 DCHECK(thread_checker_.CalledOnValidThread()); | 1638 DCHECK(thread_checker_.CalledOnValidThread()); |
1618 DCHECK_NE(nqe::internal::kInvalidThroughput, observation.value); | 1639 DCHECK_NE(nqe::internal::kInvalidThroughput, observation.value); |
1619 | 1640 |
1620 // Maybe recompute the effective connection type since a new throughput | 1641 // Maybe recompute the effective connection type since a new throughput |
1621 // observation is available. | 1642 // observation is available. |
1622 MaybeRecomputeEffectiveConnectionType(); | 1643 MaybeComputeEffectiveConnectionType(); |
1623 FOR_EACH_OBSERVER( | 1644 FOR_EACH_OBSERVER( |
1624 ThroughputObserver, throughput_observer_list_, | 1645 ThroughputObserver, throughput_observer_list_, |
1625 OnThroughputObservation(observation.value, observation.timestamp, | 1646 OnThroughputObservation(observation.value, observation.timestamp, |
1626 observation.source)); | 1647 observation.source)); |
1627 } | 1648 } |
1628 | 1649 |
1629 void NetworkQualityEstimator::OnNewThroughputObservationAvailable( | 1650 void NetworkQualityEstimator::OnNewThroughputObservationAvailable( |
1630 int32_t downstream_kbps) { | 1651 int32_t downstream_kbps) { |
1631 DCHECK(thread_checker_.CalledOnValidThread()); | 1652 DCHECK(thread_checker_.CalledOnValidThread()); |
1632 | 1653 |
1633 if (downstream_kbps == 0) | 1654 if (downstream_kbps == 0) |
1634 return; | 1655 return; |
1635 | 1656 |
1636 DCHECK_NE(nqe::internal::kInvalidThroughput, downstream_kbps); | 1657 DCHECK_NE(nqe::internal::kInvalidThroughput, downstream_kbps); |
1637 | 1658 |
1638 if (downstream_kbps > peak_network_quality_.downstream_throughput_kbps()) { | 1659 if (downstream_kbps > peak_network_quality_.downstream_throughput_kbps()) { |
1639 peak_network_quality_ = nqe::internal::NetworkQuality( | 1660 peak_network_quality_ = nqe::internal::NetworkQuality( |
1640 peak_network_quality_.http_rtt(), peak_network_quality_.transport_rtt(), | 1661 peak_network_quality_.http_rtt(), peak_network_quality_.transport_rtt(), |
1641 downstream_kbps); | 1662 downstream_kbps); |
1642 } | 1663 } |
1643 ThroughputObservation throughput_observation( | 1664 ThroughputObservation throughput_observation( |
1644 downstream_kbps, tick_clock_->NowTicks(), | 1665 downstream_kbps, tick_clock_->NowTicks(), |
1645 NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST); | 1666 NETWORK_QUALITY_OBSERVATION_SOURCE_URL_REQUEST); |
1646 downstream_throughput_kbps_observations_.AddObservation( | 1667 downstream_throughput_kbps_observations_.AddObservation( |
1647 throughput_observation); | 1668 throughput_observation); |
1648 NotifyObserversOfThroughput(throughput_observation); | 1669 NotifyObserversOfThroughput(throughput_observation); |
1649 } | 1670 } |
1650 | 1671 |
1651 void NetworkQualityEstimator::MaybeRecomputeEffectiveConnectionType() { | 1672 void NetworkQualityEstimator::MaybeComputeEffectiveConnectionType() { |
1652 DCHECK(thread_checker_.CalledOnValidThread()); | 1673 DCHECK(thread_checker_.CalledOnValidThread()); |
1653 | 1674 |
1654 const base::TimeTicks now = tick_clock_->NowTicks(); | 1675 const base::TimeTicks now = tick_clock_->NowTicks(); |
1655 // Recompute effective connection type only if | 1676 // Recompute effective connection type only if |
1656 // |effective_connection_type_recomputation_interval_| has passed since it was | 1677 // |effective_connection_type_recomputation_interval_| has passed since it was |
1657 // last computed or a connection change event was observed since the last | 1678 // last computed or a connection change event was observed since the last |
1658 // computation. Strict inequalities are used to ensure that effective | 1679 // computation. Strict inequalities are used to ensure that effective |
1659 // connection type is recomputed on connection change events even if the clock | 1680 // connection type is recomputed on connection change events even if the clock |
1660 // has not updated. | 1681 // has not updated. |
1661 if (now - last_effective_connection_type_computation_ < | 1682 if (now - last_effective_connection_type_computation_ < |
1662 effective_connection_type_recomputation_interval_ && | 1683 effective_connection_type_recomputation_interval_ && |
1663 last_connection_change_ < last_effective_connection_type_computation_ && | 1684 last_connection_change_ < last_effective_connection_type_computation_ && |
1664 // Recompute the effective connection type if the previously computed | 1685 // Recompute the effective connection type if the previously computed |
1665 // effective connection type was unknown. | 1686 // effective connection type was unknown. |
1666 effective_connection_type_ != EFFECTIVE_CONNECTION_TYPE_UNKNOWN && | 1687 effective_connection_type_ != EFFECTIVE_CONNECTION_TYPE_UNKNOWN && |
1667 // Recompute the effective connection type if the number of samples | 1688 // Recompute the effective connection type if the number of samples |
1668 // available now are more than twice in count than the number of | 1689 // available now are 50% more than the number of samples that were |
1669 // samples that were available when the effective connection type was | 1690 // available when the effective connection type was last computed. |
1670 // last computed. | 1691 rtt_observations_size_at_last_ect_computation_ * 1.5 >= |
1671 rtt_observations_size_at_last_ect_computation_ * 2 >= | |
1672 rtt_observations_.Size() && | 1692 rtt_observations_.Size() && |
1673 throughput_observations_size_at_last_ect_computation_ * 2 >= | 1693 throughput_observations_size_at_last_ect_computation_ * 1.5 >= |
1674 downstream_throughput_kbps_observations_.Size()) { | 1694 downstream_throughput_kbps_observations_.Size()) { |
1675 return; | 1695 return; |
1676 } | 1696 } |
1677 | 1697 ComputeEffectiveConnectionType(); |
1678 const EffectiveConnectionType past_type = effective_connection_type_; | |
1679 last_effective_connection_type_computation_ = now; | |
1680 effective_connection_type_ = GetEffectiveConnectionType(); | |
1681 | |
1682 if (past_type != effective_connection_type_) | |
1683 NotifyObserversOfEffectiveConnectionTypeChanged(); | |
1684 | |
1685 rtt_observations_size_at_last_ect_computation_ = rtt_observations_.Size(); | |
1686 throughput_observations_size_at_last_ect_computation_ = | |
1687 downstream_throughput_kbps_observations_.Size(); | |
1688 } | 1698 } |
1689 | 1699 |
1690 void NetworkQualityEstimator:: | 1700 void NetworkQualityEstimator:: |
1691 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1701 NotifyObserversOfEffectiveConnectionTypeChanged() { |
1692 DCHECK(thread_checker_.CalledOnValidThread()); | 1702 DCHECK(thread_checker_.CalledOnValidThread()); |
1693 DCHECK_NE(EFFECTIVE_CONNECTION_TYPE_LAST, effective_connection_type_); | 1703 DCHECK_NE(EFFECTIVE_CONNECTION_TYPE_LAST, effective_connection_type_); |
1694 | 1704 |
1695 // TODO(tbansal): Add hysteresis in the notification. | 1705 // TODO(tbansal): Add hysteresis in the notification. |
1696 FOR_EACH_OBSERVER( | 1706 FOR_EACH_OBSERVER( |
1697 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1707 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
1698 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1708 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
1699 | 1709 |
1700 // Add the estimates of the current network to the cache store. | 1710 // Add the estimates of the current network to the cache store. |
1701 if (effective_connection_type_ != EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { | 1711 if (effective_connection_type_ != EFFECTIVE_CONNECTION_TYPE_UNKNOWN) { |
1702 network_quality_store_->Add( | 1712 network_quality_store_->Add( |
1703 current_network_id_, | 1713 current_network_id_, |
1704 nqe::internal::CachedNetworkQuality( | 1714 nqe::internal::CachedNetworkQuality( |
1705 tick_clock_->NowTicks(), estimated_quality_at_last_main_frame_, | 1715 tick_clock_->NowTicks(), estimated_quality_at_last_main_frame_, |
1706 effective_connection_type_)); | 1716 effective_connection_type_)); |
1707 } | 1717 } |
1708 } | 1718 } |
1709 | 1719 |
1710 } // namespace net | 1720 } // namespace net |
OLD | NEW |