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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
87 // parameter for Wi-Fi would be "WiFi.DefaultMedianKbps". | 87 // parameter for Wi-Fi would be "WiFi.DefaultMedianKbps". |
88 const char kDefaultKbpsObservationSuffix[] = ".DefaultMedianKbps"; | 88 const char kDefaultKbpsObservationSuffix[] = ".DefaultMedianKbps"; |
89 | 89 |
90 // Suffix of the name of the variation parameter that contains the threshold | 90 // Suffix of the name of the variation parameter that contains the threshold |
91 // HTTP RTTs (in milliseconds) for different effective connection types. | 91 // HTTP RTTs (in milliseconds) for different effective connection types. |
92 // Complete name of the variation parameter would be | 92 // Complete name of the variation parameter would be |
93 // |EffectiveConnectionType|.|kThresholdURLRTTMsecSuffix|. | 93 // |EffectiveConnectionType|.|kThresholdURLRTTMsecSuffix|. |
94 const char kThresholdURLRTTMsecSuffix[] = ".ThresholdMedianHttpRTTMsec"; | 94 const char kThresholdURLRTTMsecSuffix[] = ".ThresholdMedianHttpRTTMsec"; |
95 | 95 |
96 // Suffix of the name of the variation parameter that contains the threshold | 96 // Suffix of the name of the variation parameter that contains the threshold |
| 97 // transport RTTs (in milliseconds) for different effective connection types. |
| 98 // Complete name of the variation parameter would be |
| 99 // |EffectiveConnectionType|.|kThresholdTransportRTTMsecSuffix|. |
| 100 const char kThresholdTransportRTTMsecSuffix[] = |
| 101 ".ThresholdMedianTransportRTTMsec"; |
| 102 |
| 103 // Suffix of the name of the variation parameter that contains the threshold |
97 // downlink throughput (in kbps) for different effective connection types. | 104 // downlink throughput (in kbps) for different effective connection types. |
98 // Complete name of the variation parameter would be | 105 // Complete name of the variation parameter would be |
99 // |EffectiveConnectionType|.|kThresholdKbpsSuffix|. | 106 // |EffectiveConnectionType|.|kThresholdKbpsSuffix|. |
100 const char kThresholdKbpsSuffix[] = ".ThresholdMedianKbps"; | 107 const char kThresholdKbpsSuffix[] = ".ThresholdMedianKbps"; |
101 | 108 |
102 // Computes and returns the weight multiplier per second. | 109 // Computes and returns the weight multiplier per second. |
103 // |variation_params| is the map containing all field trial parameters | 110 // |variation_params| is the map containing all field trial parameters |
104 // related to NetworkQualityEstimator field trial. | 111 // related to NetworkQualityEstimator field trial. |
105 double GetWeightMultiplierPerSecond( | 112 double GetWeightMultiplierPerSecond( |
106 const std::map<std::string, std::string>& variation_params) { | 113 const std::map<std::string, std::string>& variation_params) { |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
221 false, | 228 false, |
222 false) {} | 229 false) {} |
223 | 230 |
224 NetworkQualityEstimator::NetworkQualityEstimator( | 231 NetworkQualityEstimator::NetworkQualityEstimator( |
225 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, | 232 std::unique_ptr<ExternalEstimateProvider> external_estimates_provider, |
226 const std::map<std::string, std::string>& variation_params, | 233 const std::map<std::string, std::string>& variation_params, |
227 bool use_local_host_requests_for_tests, | 234 bool use_local_host_requests_for_tests, |
228 bool use_smaller_responses_for_tests) | 235 bool use_smaller_responses_for_tests) |
229 : algorithm_name_to_enum_({{"HttpRTTAndDownstreamThroughput", | 236 : algorithm_name_to_enum_({{"HttpRTTAndDownstreamThroughput", |
230 EffectiveConnectionTypeAlgorithm:: | 237 EffectiveConnectionTypeAlgorithm:: |
231 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT}}), | 238 HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT}, |
| 239 {"TransportRTTOrDownstreamThroughput", |
| 240 EffectiveConnectionTypeAlgorithm:: |
| 241 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT}}), |
232 use_localhost_requests_(use_local_host_requests_for_tests), | 242 use_localhost_requests_(use_local_host_requests_for_tests), |
233 use_small_responses_(use_smaller_responses_for_tests), | 243 use_small_responses_(use_smaller_responses_for_tests), |
234 weight_multiplier_per_second_( | 244 weight_multiplier_per_second_( |
235 GetWeightMultiplierPerSecond(variation_params)), | 245 GetWeightMultiplierPerSecond(variation_params)), |
236 effective_connection_type_algorithm_( | 246 effective_connection_type_algorithm_( |
237 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm( | 247 algorithm_name_to_enum_.find(GetEffectiveConnectionTypeAlgorithm( |
238 variation_params)) == algorithm_name_to_enum_.end() | 248 variation_params)) == algorithm_name_to_enum_.end() |
239 ? kDefaultEffectiveConnectionTypeAlgorithm | 249 ? kDefaultEffectiveConnectionTypeAlgorithm |
240 : algorithm_name_to_enum_ | 250 : algorithm_name_to_enum_ |
241 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) | 251 .find(GetEffectiveConnectionTypeAlgorithm(variation_params)) |
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 continue; | 379 continue; |
370 | 380 |
371 std::string connection_type_name = std::string( | 381 std::string connection_type_name = std::string( |
372 GetNameForEffectiveConnectionType(effective_connection_type)); | 382 GetNameForEffectiveConnectionType(effective_connection_type)); |
373 | 383 |
374 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; | 384 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; |
375 if (GetValueForVariationParam( | 385 if (GetValueForVariationParam( |
376 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, | 386 variation_params, connection_type_name + kThresholdURLRTTMsecSuffix, |
377 &variations_value) && | 387 &variations_value) && |
378 variations_value >= kMinimumRTTVariationParameterMsec) { | 388 variations_value >= kMinimumRTTVariationParameterMsec) { |
379 base::TimeDelta rtt(base::TimeDelta::FromMilliseconds(variations_value)); | 389 connection_thresholds_[i].set_http_rtt( |
380 connection_thresholds_[i] = nqe::internal::NetworkQuality( | 390 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); |
381 rtt, connection_thresholds_[i].transport_rtt(), | |
382 connection_thresholds_[i].downstream_throughput_kbps()); | |
383 | 391 |
384 // Verify that the RTT values are in decreasing order as the network | 392 // Verify that the RTT values are in decreasing order as the network |
385 // quality improves. | 393 // quality improves. |
386 DCHECK(i == 0 || | 394 DCHECK(i == 0 || |
387 connection_thresholds_[i - 1].http_rtt() == | 395 connection_thresholds_[i - 1].http_rtt() == |
388 nqe::internal::InvalidRTT() || | 396 nqe::internal::InvalidRTT() || |
389 rtt <= connection_thresholds_[i - 1].http_rtt()); | 397 connection_thresholds_[i].http_rtt() <= |
| 398 connection_thresholds_[i - 1].http_rtt()); |
| 399 } |
| 400 |
| 401 variations_value = kMinimumRTTVariationParameterMsec - 1; |
| 402 if (GetValueForVariationParam( |
| 403 variation_params, |
| 404 connection_type_name + kThresholdTransportRTTMsecSuffix, |
| 405 &variations_value) && |
| 406 variations_value >= kMinimumRTTVariationParameterMsec) { |
| 407 connection_thresholds_[i].set_transport_rtt( |
| 408 base::TimeDelta(base::TimeDelta::FromMilliseconds(variations_value))); |
| 409 |
| 410 // Verify that the transport RTT values are in decreasing order as the |
| 411 // network quality improves. |
| 412 DCHECK(i == 0 || |
| 413 connection_thresholds_[i - 1].transport_rtt() == |
| 414 nqe::internal::InvalidRTT() || |
| 415 connection_thresholds_[i].transport_rtt() <= |
| 416 connection_thresholds_[i - 1].transport_rtt()); |
390 } | 417 } |
391 | 418 |
392 variations_value = kMinimumThroughputVariationParameterKbps - 1; | 419 variations_value = kMinimumThroughputVariationParameterKbps - 1; |
393 if (GetValueForVariationParam(variation_params, | 420 if (GetValueForVariationParam(variation_params, |
394 connection_type_name + kThresholdKbpsSuffix, | 421 connection_type_name + kThresholdKbpsSuffix, |
395 &variations_value) && | 422 &variations_value) && |
396 variations_value >= kMinimumThroughputVariationParameterKbps) { | 423 variations_value >= kMinimumThroughputVariationParameterKbps) { |
397 int32_t throughput_kbps = variations_value; | 424 connection_thresholds_[i].set_downstream_throughput_kbps( |
398 connection_thresholds_[i] = nqe::internal::NetworkQuality( | 425 variations_value); |
399 connection_thresholds_[i].http_rtt(), | |
400 connection_thresholds_[i].transport_rtt(), throughput_kbps); | |
401 | 426 |
402 // Verify that the throughput values are in increasing order as the | 427 // Verify that the throughput values are in increasing order as the |
403 // network quality improves. | 428 // network quality improves. |
404 DCHECK(i == 0 || | 429 DCHECK(i == 0 || |
405 connection_thresholds_[i - 1].downstream_throughput_kbps() == | 430 connection_thresholds_[i - 1].downstream_throughput_kbps() == |
406 kMinimumThroughputVariationParameterKbps || | 431 kMinimumThroughputVariationParameterKbps || |
407 throughput_kbps >= | 432 connection_thresholds_[i].downstream_throughput_kbps() >= |
408 connection_thresholds_[i - 1].downstream_throughput_kbps()); | 433 connection_thresholds_[i - 1].downstream_throughput_kbps()); |
409 } | 434 } |
410 } | 435 } |
411 } | 436 } |
412 | 437 |
413 void NetworkQualityEstimator::AddDefaultEstimates() { | 438 void NetworkQualityEstimator::AddDefaultEstimates() { |
414 DCHECK(thread_checker_.CalledOnValidThread()); | 439 DCHECK(thread_checker_.CalledOnValidThread()); |
415 | 440 |
416 if (default_observations_[current_network_id_.type].http_rtt() != | 441 if (default_observations_[current_network_id_.type].http_rtt() != |
417 nqe::internal::InvalidRTT()) { | 442 nqe::internal::InvalidRTT()) { |
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
913 return GetRecentEffectiveConnectionType(base::TimeTicks()); | 938 return GetRecentEffectiveConnectionType(base::TimeTicks()); |
914 } | 939 } |
915 | 940 |
916 NetworkQualityEstimator::EffectiveConnectionType | 941 NetworkQualityEstimator::EffectiveConnectionType |
917 NetworkQualityEstimator::GetRecentEffectiveConnectionType( | 942 NetworkQualityEstimator::GetRecentEffectiveConnectionType( |
918 const base::TimeTicks& start_time) const { | 943 const base::TimeTicks& start_time) const { |
919 DCHECK(thread_checker_.CalledOnValidThread()); | 944 DCHECK(thread_checker_.CalledOnValidThread()); |
920 | 945 |
921 if (effective_connection_type_algorithm_ == | 946 if (effective_connection_type_algorithm_ == |
922 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { | 947 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { |
923 return GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | 948 return GetRecentEffectiveConnectionTypeUsingMetrics( |
924 start_time); | 949 start_time, NetworkQualityEstimator::MetricUsage:: |
| 950 MUST_BE_USED /* http_rtt_metric */, |
| 951 NetworkQualityEstimator::MetricUsage:: |
| 952 DO_NOT_USE /* transport_rtt_metric */, |
| 953 NetworkQualityEstimator::MetricUsage:: |
| 954 MUST_BE_USED /* downstream_throughput_kbps_metric */); |
| 955 } |
| 956 if (effective_connection_type_algorithm_ == |
| 957 EffectiveConnectionTypeAlgorithm:: |
| 958 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT) { |
| 959 return GetRecentEffectiveConnectionTypeUsingMetrics( |
| 960 start_time, |
| 961 NetworkQualityEstimator::MetricUsage::DO_NOT_USE /* http_rtt_metric */, |
| 962 NetworkQualityEstimator::MetricUsage:: |
| 963 USE_IF_AVAILABLE /* transport_rtt_metric */, |
| 964 NetworkQualityEstimator::MetricUsage:: |
| 965 USE_IF_AVAILABLE /* downstream_throughput_kbps_metric */); |
925 } | 966 } |
926 // Add additional algorithms here. | 967 // Add additional algorithms here. |
927 NOTREACHED(); | 968 NOTREACHED(); |
928 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 969 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
929 } | 970 } |
930 | 971 |
931 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: | 972 NetworkQualityEstimator::EffectiveConnectionType |
932 GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | 973 NetworkQualityEstimator::GetRecentEffectiveConnectionTypeUsingMetrics( |
933 const base::TimeTicks& start_time) const { | 974 const base::TimeTicks& start_time, |
| 975 NetworkQualityEstimator::MetricUsage http_rtt_metric, |
| 976 NetworkQualityEstimator::MetricUsage transport_rtt_metric, |
| 977 NetworkQualityEstimator::MetricUsage downstream_throughput_kbps_metric) |
| 978 const { |
934 DCHECK(thread_checker_.CalledOnValidThread()); | 979 DCHECK(thread_checker_.CalledOnValidThread()); |
935 | 980 |
936 // If the device is currently offline, then return | 981 // If the device is currently offline, then return |
937 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. | 982 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. |
938 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) | 983 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) |
939 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; | 984 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; |
940 | 985 |
941 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); | 986 base::TimeDelta http_rtt = nqe::internal::InvalidRTT(); |
942 if (!GetRecentHttpRTTMedian(start_time, &http_rtt)) | 987 if (http_rtt_metric != NetworkQualityEstimator::MetricUsage::DO_NOT_USE && |
| 988 !GetRecentHttpRTTMedian(start_time, &http_rtt)) { |
943 http_rtt = nqe::internal::InvalidRTT(); | 989 http_rtt = nqe::internal::InvalidRTT(); |
| 990 } |
| 991 |
| 992 base::TimeDelta transport_rtt = nqe::internal::InvalidRTT(); |
| 993 if (transport_rtt_metric != |
| 994 NetworkQualityEstimator::MetricUsage::DO_NOT_USE && |
| 995 !GetRecentTransportRTTMedian(start_time, &transport_rtt)) { |
| 996 transport_rtt = nqe::internal::InvalidRTT(); |
| 997 } |
944 | 998 |
945 int32_t kbps = nqe::internal::kInvalidThroughput; | 999 int32_t kbps = nqe::internal::kInvalidThroughput; |
946 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) | 1000 if (downstream_throughput_kbps_metric != |
| 1001 NetworkQualityEstimator::MetricUsage::DO_NOT_USE && |
| 1002 !GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) { |
947 kbps = nqe::internal::kInvalidThroughput; | 1003 kbps = nqe::internal::kInvalidThroughput; |
| 1004 } |
948 | 1005 |
949 if (http_rtt == nqe::internal::InvalidRTT() || | 1006 if (http_rtt == nqe::internal::InvalidRTT() && |
950 kbps == nqe::internal::kInvalidThroughput) { | 1007 http_rtt_metric == NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { |
951 // Quality of the current network is unknown. | |
952 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 1008 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
953 } | 1009 } |
954 | 1010 |
| 1011 if (transport_rtt == nqe::internal::InvalidRTT() && |
| 1012 transport_rtt_metric == |
| 1013 NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { |
| 1014 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 1015 } |
| 1016 |
| 1017 if (kbps == nqe::internal::kInvalidThroughput && |
| 1018 downstream_throughput_kbps_metric == |
| 1019 NetworkQualityEstimator::MetricUsage::MUST_BE_USED) { |
| 1020 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 1021 } |
| 1022 |
| 1023 if (http_rtt == nqe::internal::InvalidRTT() && |
| 1024 transport_rtt == nqe::internal::InvalidRTT() && |
| 1025 kbps == nqe::internal::kInvalidThroughput) { |
| 1026 // None of the metrics are available. |
| 1027 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 1028 } |
| 1029 |
955 // Search from the slowest connection type to the fastest to find the | 1030 // Search from the slowest connection type to the fastest to find the |
956 // EffectiveConnectionType that best matches the current connection's | 1031 // EffectiveConnectionType that best matches the current connection's |
957 // performance. The match is done by comparing RTT and throughput. | 1032 // performance. The match is done by comparing RTT and throughput. |
958 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 1033 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
959 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | 1034 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); |
960 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | 1035 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
961 continue; | 1036 continue; |
962 bool estimated_http_rtt_is_higher_than_threshold = | 1037 |
| 1038 const bool estimated_http_rtt_is_higher_than_threshold = |
963 http_rtt != nqe::internal::InvalidRTT() && | 1039 http_rtt != nqe::internal::InvalidRTT() && |
964 connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && | 1040 connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && |
965 http_rtt >= connection_thresholds_[i].http_rtt(); | 1041 http_rtt >= connection_thresholds_[i].http_rtt(); |
966 bool estimated_throughput_is_lower_than_threshold = | 1042 |
| 1043 const bool estimated_transport_rtt_is_higher_than_threshold = |
| 1044 transport_rtt != nqe::internal::InvalidRTT() && |
| 1045 connection_thresholds_[i].transport_rtt() != |
| 1046 nqe::internal::InvalidRTT() && |
| 1047 transport_rtt >= connection_thresholds_[i].transport_rtt(); |
| 1048 |
| 1049 const bool estimated_throughput_is_lower_than_threshold = |
967 kbps != nqe::internal::kInvalidThroughput && | 1050 kbps != nqe::internal::kInvalidThroughput && |
968 connection_thresholds_[i].downstream_throughput_kbps() != | 1051 connection_thresholds_[i].downstream_throughput_kbps() != |
969 nqe::internal::kInvalidThroughput && | 1052 nqe::internal::kInvalidThroughput && |
970 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); | 1053 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); |
971 | 1054 |
972 // Return |type| as the effective connection type if the current network's | |
973 // RTT is worse than the threshold RTT for |type|, or if the current | |
974 // network's throughput is lower than the threshold throughput for |type|. | |
975 if (estimated_http_rtt_is_higher_than_threshold || | 1055 if (estimated_http_rtt_is_higher_than_threshold || |
| 1056 estimated_transport_rtt_is_higher_than_threshold || |
976 estimated_throughput_is_lower_than_threshold) { | 1057 estimated_throughput_is_lower_than_threshold) { |
977 return type; | 1058 return type; |
978 } | 1059 } |
979 } | 1060 } |
980 // Return the fastest connection type. | 1061 // Return the fastest connection type. |
981 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - | 1062 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - |
982 1); | 1063 1); |
983 } | 1064 } |
984 | 1065 |
985 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( | 1066 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1391 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1472 NotifyObserversOfEffectiveConnectionTypeChanged() { |
1392 DCHECK(thread_checker_.CalledOnValidThread()); | 1473 DCHECK(thread_checker_.CalledOnValidThread()); |
1393 | 1474 |
1394 // TODO(tbansal): Add hysteresis in the notification. | 1475 // TODO(tbansal): Add hysteresis in the notification. |
1395 FOR_EACH_OBSERVER( | 1476 FOR_EACH_OBSERVER( |
1396 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1477 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
1397 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1478 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
1398 } | 1479 } |
1399 | 1480 |
1400 } // namespace net | 1481 } // namespace net |
OLD | NEW |