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 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", | |
|
Not at Google. Contact bengr
2016/07/06 19:04:07
This is brittle because it allows adding an entry
tbansal1
2016/07/06 23:17:32
That error would be caught by DCHECK below. See li
Not at Google. Contact bengr
2016/07/07 00:03:04
Macro does not have this issue. You will get a com
tbansal1
2016/07/07 16:47:32
Agreed. Right now this error is captured using NQE
Not at Google. Contact bengr
2016/07/07 17:19:17
It is easy to map strings to enums. You just use a
tbansal1
2016/07/07 18:01:32
"if" condtional does not catch duplicates in value
Not at Google. Contact bengr
2016/07/07 19:10:49
We don't rely on the switch to catch duplicates. T
tbansal1
2016/07/07 22:47:26
Added TODO. For now the duplicates are catched usi
| |
| 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 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 379 connection_thresholds_[i].downstream_throughput_kbps()); | 389 connection_thresholds_[i].downstream_throughput_kbps()); |
| 380 | 390 |
| 381 // Verify that the RTT values are in decreasing order as the network | 391 // Verify that the RTT values are in decreasing order as the network |
| 382 // quality improves. | 392 // quality improves. |
| 383 DCHECK(i == 0 || | 393 DCHECK(i == 0 || |
| 384 connection_thresholds_[i - 1].http_rtt() == | 394 connection_thresholds_[i - 1].http_rtt() == |
| 385 nqe::internal::InvalidRTT() || | 395 nqe::internal::InvalidRTT() || |
| 386 rtt <= connection_thresholds_[i - 1].http_rtt()); | 396 rtt <= connection_thresholds_[i - 1].http_rtt()); |
| 387 } | 397 } |
| 388 | 398 |
| 399 variations_value = kMinimumRTTVariationParameterMsec - 1; | |
|
Not at Google. Contact bengr
2016/07/07 00:03:04
This block is extremely similar to the block above
tbansal1
2016/07/07 16:47:32
I am not sure of a better way to combine them.
| |
| 400 if (GetValueForVariationParam( | |
| 401 variation_params, | |
| 402 connection_type_name + kThresholdTransportRTTMsecSuffix, | |
| 403 &variations_value) && | |
| 404 variations_value >= kMinimumRTTVariationParameterMsec) { | |
| 405 base::TimeDelta transport_rtt( | |
| 406 base::TimeDelta::FromMilliseconds(variations_value)); | |
| 407 connection_thresholds_[i] = nqe::internal::NetworkQuality( | |
|
Not at Google. Contact bengr
2016/07/07 00:03:04
Any reason to create new instance of NetworkQualit
tbansal1
2016/07/07 16:47:32
Done.
| |
| 408 connection_thresholds_[i].http_rtt(), transport_rtt, | |
| 409 connection_thresholds_[i].downstream_throughput_kbps()); | |
| 410 | |
| 411 // Verify that the transport RTT values are in decreasing order as the | |
| 412 // network quality improves. | |
| 413 DCHECK(i == 0 || | |
| 414 connection_thresholds_[i - 1].transport_rtt() == | |
| 415 nqe::internal::InvalidRTT() || | |
| 416 transport_rtt <= connection_thresholds_[i - 1].transport_rtt()); | |
| 417 } | |
| 418 | |
| 389 variations_value = kMinimumThroughputVariationParameterKbps - 1; | 419 variations_value = kMinimumThroughputVariationParameterKbps - 1; |
| 390 if (GetValueForVariationParam(variation_params, | 420 if (GetValueForVariationParam(variation_params, |
| 391 connection_type_name + kThresholdKbpsSuffix, | 421 connection_type_name + kThresholdKbpsSuffix, |
| 392 &variations_value) && | 422 &variations_value) && |
| 393 variations_value >= kMinimumThroughputVariationParameterKbps) { | 423 variations_value >= kMinimumThroughputVariationParameterKbps) { |
| 394 int32_t throughput_kbps = variations_value; | 424 int32_t throughput_kbps = variations_value; |
| 395 connection_thresholds_[i] = nqe::internal::NetworkQuality( | 425 connection_thresholds_[i] = nqe::internal::NetworkQuality( |
| 396 connection_thresholds_[i].http_rtt(), | 426 connection_thresholds_[i].http_rtt(), |
| 397 connection_thresholds_[i].transport_rtt(), throughput_kbps); | 427 connection_thresholds_[i].transport_rtt(), throughput_kbps); |
| 398 | 428 |
| (...skipping 486 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 885 NetworkQualityEstimator::EffectiveConnectionType | 915 NetworkQualityEstimator::EffectiveConnectionType |
| 886 NetworkQualityEstimator::GetRecentEffectiveConnectionType( | 916 NetworkQualityEstimator::GetRecentEffectiveConnectionType( |
| 887 const base::TimeTicks& start_time) const { | 917 const base::TimeTicks& start_time) const { |
| 888 DCHECK(thread_checker_.CalledOnValidThread()); | 918 DCHECK(thread_checker_.CalledOnValidThread()); |
| 889 | 919 |
| 890 if (effective_connection_type_algorithm_ == | 920 if (effective_connection_type_algorithm_ == |
| 891 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { | 921 EffectiveConnectionTypeAlgorithm::HTTP_RTT_AND_DOWNSTREAM_THROUGHOUT) { |
| 892 return GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | 922 return GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( |
| 893 start_time); | 923 start_time); |
| 894 } | 924 } |
| 925 if (effective_connection_type_algorithm_ == | |
| 926 EffectiveConnectionTypeAlgorithm:: | |
| 927 TRANSPORT_RTT_OR_DOWNSTREAM_THROUGHOUT) { | |
| 928 return GetRecentEffectiveConnectionTypeTransportRTTOrDownstreamThroughput( | |
| 929 start_time); | |
| 930 } | |
| 895 // Add additional algorithms here. | 931 // Add additional algorithms here. |
| 896 NOTREACHED(); | 932 NOTREACHED(); |
| 897 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 933 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 898 } | 934 } |
| 899 | 935 |
| 900 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: | 936 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: |
| 901 GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( | 937 GetRecentEffectiveConnectionTypeHttpRTTAndDownstreamThroughput( |
| 902 const base::TimeTicks& start_time) const { | 938 const base::TimeTicks& start_time) const { |
| 903 DCHECK(thread_checker_.CalledOnValidThread()); | 939 DCHECK(thread_checker_.CalledOnValidThread()); |
| 904 | 940 |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 921 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | 957 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 922 } | 958 } |
| 923 | 959 |
| 924 // Search from the slowest connection type to the fastest to find the | 960 // Search from the slowest connection type to the fastest to find the |
| 925 // EffectiveConnectionType that best matches the current connection's | 961 // EffectiveConnectionType that best matches the current connection's |
| 926 // performance. The match is done by comparing RTT and throughput. | 962 // performance. The match is done by comparing RTT and throughput. |
| 927 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | 963 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 928 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | 964 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); |
| 929 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | 965 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
| 930 continue; | 966 continue; |
| 931 bool estimated_http_rtt_is_higher_than_threshold = | 967 const bool estimated_http_rtt_is_higher_than_threshold = |
| 932 http_rtt != nqe::internal::InvalidRTT() && | 968 http_rtt != nqe::internal::InvalidRTT() && |
| 933 connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && | 969 connection_thresholds_[i].http_rtt() != nqe::internal::InvalidRTT() && |
| 934 http_rtt >= connection_thresholds_[i].http_rtt(); | 970 http_rtt >= connection_thresholds_[i].http_rtt(); |
| 935 bool estimated_throughput_is_lower_than_threshold = | 971 const bool estimated_throughput_is_lower_than_threshold = |
| 936 kbps != nqe::internal::kInvalidThroughput && | 972 kbps != nqe::internal::kInvalidThroughput && |
| 937 connection_thresholds_[i].downstream_throughput_kbps() != | 973 connection_thresholds_[i].downstream_throughput_kbps() != |
| 938 nqe::internal::kInvalidThroughput && | 974 nqe::internal::kInvalidThroughput && |
| 939 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); | 975 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); |
| 940 | 976 |
| 941 // Return |type| as the effective connection type if the current network's | 977 // 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 | 978 // 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|. | 979 // network's throughput is lower than the threshold throughput for |type|. |
| 944 if (estimated_http_rtt_is_higher_than_threshold || | 980 if (estimated_http_rtt_is_higher_than_threshold || |
| 945 estimated_throughput_is_lower_than_threshold) { | 981 estimated_throughput_is_lower_than_threshold) { |
| 946 return type; | 982 return type; |
| 947 } | 983 } |
| 948 } | 984 } |
| 949 // Return the fastest connection type. | 985 // Return the fastest connection type. |
| 950 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - | 986 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - |
| 951 1); | 987 1); |
| 952 } | 988 } |
| 953 | 989 |
| 990 NetworkQualityEstimator::EffectiveConnectionType NetworkQualityEstimator:: | |
| 991 GetRecentEffectiveConnectionTypeTransportRTTOrDownstreamThroughput( | |
| 992 const base::TimeTicks& start_time) const { | |
| 993 DCHECK(thread_checker_.CalledOnValidThread()); | |
| 994 | |
| 995 // If the device is currently offline, then return | |
|
Not at Google. Contact bengr
2016/07/06 19:04:07
FWIW code is very readable, so this comment seems
tbansal1
2016/07/06 23:17:32
Done.
| |
| 996 // EFFECTIVE_CONNECTION_TYPE_OFFLINE. | |
| 997 if (GetCurrentNetworkID().type == NetworkChangeNotifier::CONNECTION_NONE) | |
| 998 return EFFECTIVE_CONNECTION_TYPE_OFFLINE; | |
| 999 | |
| 1000 base::TimeDelta transport_rtt = nqe::internal::InvalidRTT(); | |
| 1001 if (!GetRecentTransportRTTMedian(start_time, &transport_rtt)) | |
| 1002 transport_rtt = nqe::internal::InvalidRTT(); | |
|
Not at Google. Contact bengr
2016/07/06 19:04:07
Can we have GetRecentTransportRTTMedian(..) set tr
tbansal1
2016/07/06 23:17:32
Yeah, I need to fix that. It is easier now since G
Not at Google. Contact bengr
2016/07/07 00:03:04
Add TODO?
tbansal1
2016/07/07 16:47:32
Done in .h file.
| |
| 1003 | |
| 1004 int32_t kbps = nqe::internal::kInvalidThroughput; | |
| 1005 if (!GetRecentMedianDownlinkThroughputKbps(start_time, &kbps)) | |
| 1006 kbps = nqe::internal::kInvalidThroughput; | |
|
Not at Google. Contact bengr
2016/07/06 19:04:07
Similar to above comment: Can GetRecentMedianDownl
tbansal1
2016/07/06 23:17:32
same as above.
Not at Google. Contact bengr
2016/07/07 00:03:04
Acknowledged.
| |
| 1007 | |
| 1008 if (transport_rtt == nqe::internal::InvalidRTT() && | |
| 1009 kbps == nqe::internal::kInvalidThroughput) { | |
| 1010 // Quality of the current network is unknown. | |
| 1011 return EFFECTIVE_CONNECTION_TYPE_UNKNOWN; | |
| 1012 } | |
| 1013 | |
| 1014 // Search from the slowest connection type to the fastest to find the | |
| 1015 // EffectiveConnectionType that best matches the current connection's | |
| 1016 // performance. The match is done by comparing RTT and throughput. | |
| 1017 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { | |
| 1018 EffectiveConnectionType type = static_cast<EffectiveConnectionType>(i); | |
| 1019 if (i == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) | |
| 1020 continue; | |
| 1021 const bool estimated_transport_rtt_is_higher_than_threshold = | |
| 1022 transport_rtt != nqe::internal::InvalidRTT() && | |
| 1023 connection_thresholds_[i].transport_rtt() != | |
| 1024 nqe::internal::InvalidRTT() && | |
| 1025 transport_rtt >= connection_thresholds_[i].transport_rtt(); | |
| 1026 const bool estimated_throughput_is_lower_than_threshold = | |
| 1027 kbps != nqe::internal::kInvalidThroughput && | |
| 1028 connection_thresholds_[i].downstream_throughput_kbps() != | |
| 1029 nqe::internal::kInvalidThroughput && | |
| 1030 kbps <= connection_thresholds_[i].downstream_throughput_kbps(); | |
| 1031 | |
| 1032 // Return |type| as the effective connection type if the current network's | |
| 1033 // transport RTT is worse than the threshold RTT for |type|, or if the | |
| 1034 // current network's throughput is lower than the threshold throughput for | |
| 1035 // |type|. | |
| 1036 if (estimated_transport_rtt_is_higher_than_threshold || | |
| 1037 estimated_throughput_is_lower_than_threshold) { | |
| 1038 return type; | |
| 1039 } | |
| 1040 } | |
| 1041 // Return the fastest connection type. | |
| 1042 return static_cast<EffectiveConnectionType>(EFFECTIVE_CONNECTION_TYPE_LAST - | |
| 1043 1); | |
| 1044 } | |
| 1045 | |
| 954 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( | 1046 void NetworkQualityEstimator::AddEffectiveConnectionTypeObserver( |
| 955 EffectiveConnectionTypeObserver* observer) { | 1047 EffectiveConnectionTypeObserver* observer) { |
| 956 DCHECK(thread_checker_.CalledOnValidThread()); | 1048 DCHECK(thread_checker_.CalledOnValidThread()); |
| 957 effective_connection_type_observer_list_.AddObserver(observer); | 1049 effective_connection_type_observer_list_.AddObserver(observer); |
| 958 } | 1050 } |
| 959 | 1051 |
| 960 void NetworkQualityEstimator::RemoveEffectiveConnectionTypeObserver( | 1052 void NetworkQualityEstimator::RemoveEffectiveConnectionTypeObserver( |
| 961 EffectiveConnectionTypeObserver* observer) { | 1053 EffectiveConnectionTypeObserver* observer) { |
| 962 DCHECK(thread_checker_.CalledOnValidThread()); | 1054 DCHECK(thread_checker_.CalledOnValidThread()); |
| 963 effective_connection_type_observer_list_.RemoveObserver(observer); | 1055 effective_connection_type_observer_list_.RemoveObserver(observer); |
| (...skipping 396 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1360 NotifyObserversOfEffectiveConnectionTypeChanged() { | 1452 NotifyObserversOfEffectiveConnectionTypeChanged() { |
| 1361 DCHECK(thread_checker_.CalledOnValidThread()); | 1453 DCHECK(thread_checker_.CalledOnValidThread()); |
| 1362 | 1454 |
| 1363 // TODO(tbansal): Add hysteresis in the notification. | 1455 // TODO(tbansal): Add hysteresis in the notification. |
| 1364 FOR_EACH_OBSERVER( | 1456 FOR_EACH_OBSERVER( |
| 1365 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, | 1457 EffectiveConnectionTypeObserver, effective_connection_type_observer_list_, |
| 1366 OnEffectiveConnectionTypeChanged(effective_connection_type_)); | 1458 OnEffectiveConnectionTypeChanged(effective_connection_type_)); |
| 1367 } | 1459 } |
| 1368 | 1460 |
| 1369 } // namespace net | 1461 } // namespace net |
| OLD | NEW |