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