Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(18)

Side by Side Diff: net/nqe/network_quality_estimator.cc

Issue 2113363002: NQE: Add Transport RTT based GetECT algorithm (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/nqe/network_quality_estimator.h ('k') | net/nqe/network_quality_estimator_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/nqe/network_quality_estimator.h ('k') | net/nqe/network_quality_estimator_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698