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

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: Add TODO 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
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",
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698