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 |