| OLD | NEW |
| (Empty) | |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "net/nqe/network_quality_estimator_params.h" |
| 6 |
| 7 #include <stdint.h> |
| 8 |
| 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/time/time.h" |
| 11 |
| 12 namespace { |
| 13 |
| 14 // Minimum valid value of the variation parameter that holds RTT (in |
| 15 // milliseconds) values. |
| 16 static const int kMinimumRTTVariationParameterMsec = 1; |
| 17 |
| 18 // Minimum valid value of the variation parameter that holds throughput (in |
| 19 // kilobits per second) values. |
| 20 static const int kMinimumThroughputVariationParameterKbps = 1; |
| 21 |
| 22 // Returns the value of |parameter_name| read from |variation_params|. If the |
| 23 // value is unavailable from |variation_params|, then |default_value| is |
| 24 // returned. |
| 25 int64_t GetValueForVariationParam( |
| 26 const std::map<std::string, std::string>& variation_params, |
| 27 const std::string& parameter_name, |
| 28 int64_t default_value) { |
| 29 const auto it = variation_params.find(parameter_name); |
| 30 int64_t variations_value = default_value; |
| 31 if (it != variation_params.end() && |
| 32 base::StringToInt64(it->second, &variations_value)) { |
| 33 return variations_value; |
| 34 } |
| 35 return default_value; |
| 36 } |
| 37 |
| 38 // Returns the variation value for |parameter_name|. If the value is |
| 39 // unavailable, |default_value| is returned. |
| 40 double GetDoubleValueForVariationParamWithDefaultValue( |
| 41 const std::map<std::string, std::string>& variation_params, |
| 42 const std::string& parameter_name, |
| 43 double default_value) { |
| 44 const auto it = variation_params.find(parameter_name); |
| 45 if (it == variation_params.end()) |
| 46 return default_value; |
| 47 |
| 48 double variations_value = default_value; |
| 49 if (!base::StringToDouble(it->second, &variations_value)) |
| 50 return default_value; |
| 51 return variations_value; |
| 52 } |
| 53 |
| 54 // Returns the variation value for |parameter_name|. If the value is |
| 55 // unavailable, |default_value| is returned. |
| 56 std::string GetStringValueForVariationParamWithDefaultValue( |
| 57 const std::map<std::string, std::string>& variation_params, |
| 58 const std::string& parameter_name, |
| 59 const std::string& default_value) { |
| 60 const auto it = variation_params.find(parameter_name); |
| 61 if (it == variation_params.end()) |
| 62 return default_value; |
| 63 return it->second; |
| 64 } |
| 65 |
| 66 } // namespace |
| 67 |
| 68 namespace net { |
| 69 |
| 70 namespace nqe { |
| 71 |
| 72 namespace internal { |
| 73 |
| 74 std::string GetEffectiveConnectionTypeAlgorithm( |
| 75 const std::map<std::string, std::string>& variation_params) { |
| 76 const auto it = variation_params.find("effective_connection_type_algorithm"); |
| 77 if (it == variation_params.end()) |
| 78 return std::string(); |
| 79 return it->second; |
| 80 } |
| 81 |
| 82 double GetWeightMultiplierPerSecond( |
| 83 const std::map<std::string, std::string>& variation_params) { |
| 84 // Default value of the half life (in seconds) for computing time weighted |
| 85 // percentiles. Every half life, the weight of all observations reduces by |
| 86 // half. Lowering the half life would reduce the weight of older values |
| 87 // faster. |
| 88 int half_life_seconds = 60; |
| 89 int32_t variations_value = 0; |
| 90 auto it = variation_params.find("HalfLifeSeconds"); |
| 91 if (it != variation_params.end() && |
| 92 base::StringToInt(it->second, &variations_value) && |
| 93 variations_value >= 1) { |
| 94 half_life_seconds = variations_value; |
| 95 } |
| 96 DCHECK_GT(half_life_seconds, 0); |
| 97 return pow(0.5, 1.0 / half_life_seconds); |
| 98 } |
| 99 |
| 100 const char* GetNameForConnectionType( |
| 101 net::NetworkChangeNotifier::ConnectionType connection_type) { |
| 102 switch (connection_type) { |
| 103 case net::NetworkChangeNotifier::CONNECTION_UNKNOWN: |
| 104 return "Unknown"; |
| 105 case net::NetworkChangeNotifier::CONNECTION_ETHERNET: |
| 106 return "Ethernet"; |
| 107 case net::NetworkChangeNotifier::CONNECTION_WIFI: |
| 108 return "WiFi"; |
| 109 case net::NetworkChangeNotifier::CONNECTION_2G: |
| 110 return "2G"; |
| 111 case net::NetworkChangeNotifier::CONNECTION_3G: |
| 112 return "3G"; |
| 113 case net::NetworkChangeNotifier::CONNECTION_4G: |
| 114 return "4G"; |
| 115 case net::NetworkChangeNotifier::CONNECTION_NONE: |
| 116 return "None"; |
| 117 case net::NetworkChangeNotifier::CONNECTION_BLUETOOTH: |
| 118 return "Bluetooth"; |
| 119 default: |
| 120 NOTREACHED(); |
| 121 break; |
| 122 } |
| 123 return ""; |
| 124 } |
| 125 |
| 126 void ObtainDefaultObservations( |
| 127 const std::map<std::string, std::string>& variation_params, |
| 128 NetworkQuality default_observations[]) { |
| 129 for (size_t i = 0; i < NetworkChangeNotifier::CONNECTION_LAST; ++i) { |
| 130 NetworkChangeNotifier::ConnectionType type = |
| 131 static_cast<NetworkChangeNotifier::ConnectionType>(i); |
| 132 DCHECK_EQ(InvalidRTT(), default_observations[i].http_rtt()); |
| 133 DCHECK_EQ(InvalidRTT(), default_observations[i].transport_rtt()); |
| 134 DCHECK_EQ(kInvalidThroughput, |
| 135 default_observations[i].downstream_throughput_kbps()); |
| 136 |
| 137 base::TimeDelta default_rtt = InvalidRTT(); |
| 138 int32_t variations_value = kMinimumRTTVariationParameterMsec - 1; |
| 139 std::string parameter_name = std::string(GetNameForConnectionType(type)) |
| 140 .append(".DefaultMedianRTTMsec"); |
| 141 auto it = variation_params.find(parameter_name); |
| 142 |
| 143 if (it != variation_params.end() && |
| 144 base::StringToInt(it->second, &variations_value) && |
| 145 variations_value >= kMinimumRTTVariationParameterMsec) { |
| 146 default_rtt = base::TimeDelta::FromMilliseconds(variations_value); |
| 147 } |
| 148 |
| 149 int32_t downstream_throughput_kbps = kInvalidThroughput; |
| 150 variations_value = kMinimumThroughputVariationParameterKbps - 1; |
| 151 parameter_name = std::string(GetNameForConnectionType(type)) |
| 152 .append(".DefaultMedianKbps"); |
| 153 it = variation_params.find(parameter_name); |
| 154 |
| 155 if (it != variation_params.end() && |
| 156 base::StringToInt(it->second, &variations_value) && |
| 157 variations_value >= kMinimumThroughputVariationParameterKbps) { |
| 158 downstream_throughput_kbps = variations_value; |
| 159 } |
| 160 |
| 161 default_observations[i] = |
| 162 NetworkQuality(default_rtt, default_observations[i].transport_rtt(), |
| 163 downstream_throughput_kbps); |
| 164 } |
| 165 } |
| 166 |
| 167 void ObtainEffectiveConnectionTypeModelParams( |
| 168 const std::map<std::string, std::string>& variation_params, |
| 169 NetworkQuality connection_thresholds[]) { |
| 170 // First set the default thresholds. |
| 171 NetworkQuality default_effective_connection_type_thresholds |
| 172 [EffectiveConnectionType::EFFECTIVE_CONNECTION_TYPE_LAST]; |
| 173 |
| 174 default_effective_connection_type_thresholds |
| 175 [EFFECTIVE_CONNECTION_TYPE_SLOW_2G] = NetworkQuality( |
| 176 // Set to 2010 milliseconds, which corresponds to the 33rd percentile |
| 177 // of 2G HTTP RTT observations on Android. |
| 178 base::TimeDelta::FromMilliseconds(2010), |
| 179 // Set to 1870 milliseconds, which corresponds to the 33rd percentile |
| 180 // of 2G transport RTT observations on Android. |
| 181 base::TimeDelta::FromMilliseconds(1870), kInvalidThroughput); |
| 182 |
| 183 default_effective_connection_type_thresholds[EFFECTIVE_CONNECTION_TYPE_2G] = |
| 184 NetworkQuality( |
| 185 // Set to 1420 milliseconds, which corresponds to 50th percentile of |
| 186 // 2G |
| 187 // HTTP RTT observations on Android. |
| 188 base::TimeDelta::FromMilliseconds(1420), |
| 189 // Set to 1280 milliseconds, which corresponds to 50th percentile of |
| 190 // 2G |
| 191 // transport RTT observations on Android. |
| 192 base::TimeDelta::FromMilliseconds(1280), kInvalidThroughput); |
| 193 |
| 194 default_effective_connection_type_thresholds[EFFECTIVE_CONNECTION_TYPE_3G] = |
| 195 NetworkQuality( |
| 196 // Set to 273 milliseconds, which corresponds to 50th percentile of |
| 197 // 3G HTTP RTT observations on Android. |
| 198 base::TimeDelta::FromMilliseconds(273), |
| 199 // Set to 204 milliseconds, which corresponds to 50th percentile of |
| 200 // 3G transport RTT observations on Android. |
| 201 base::TimeDelta::FromMilliseconds(204), kInvalidThroughput); |
| 202 |
| 203 for (size_t i = 0; i < EFFECTIVE_CONNECTION_TYPE_LAST; ++i) { |
| 204 EffectiveConnectionType effective_connection_type = |
| 205 static_cast<EffectiveConnectionType>(i); |
| 206 DCHECK_EQ(InvalidRTT(), connection_thresholds[i].http_rtt()); |
| 207 DCHECK_EQ(InvalidRTT(), connection_thresholds[i].transport_rtt()); |
| 208 DCHECK_EQ(kInvalidThroughput, |
| 209 connection_thresholds[i].downstream_throughput_kbps()); |
| 210 if (effective_connection_type == EFFECTIVE_CONNECTION_TYPE_UNKNOWN) |
| 211 continue; |
| 212 |
| 213 std::string connection_type_name = std::string( |
| 214 GetNameForEffectiveConnectionType(effective_connection_type)); |
| 215 |
| 216 connection_thresholds[i].set_http_rtt( |
| 217 base::TimeDelta::FromMilliseconds(GetValueForVariationParam( |
| 218 variation_params, |
| 219 connection_type_name + ".ThresholdMedianHttpRTTMsec", |
| 220 default_effective_connection_type_thresholds[i] |
| 221 .http_rtt() |
| 222 .InMilliseconds()))); |
| 223 |
| 224 connection_thresholds[i].set_transport_rtt( |
| 225 base::TimeDelta::FromMilliseconds(GetValueForVariationParam( |
| 226 variation_params, |
| 227 connection_type_name + ".ThresholdMedianTransportRTTMsec", |
| 228 default_effective_connection_type_thresholds[i] |
| 229 .transport_rtt() |
| 230 .InMilliseconds()))); |
| 231 |
| 232 connection_thresholds[i].set_downstream_throughput_kbps( |
| 233 GetValueForVariationParam( |
| 234 variation_params, connection_type_name + ".ThresholdMedianKbps", |
| 235 default_effective_connection_type_thresholds[i] |
| 236 .downstream_throughput_kbps())); |
| 237 DCHECK(i == 0 || |
| 238 connection_thresholds[i].IsFaster(connection_thresholds[i - 1])); |
| 239 } |
| 240 } |
| 241 |
| 242 double correlation_uma_logging_probability( |
| 243 const std::map<std::string, std::string>& variation_params) { |
| 244 double correlation_uma_logging_probability = |
| 245 GetDoubleValueForVariationParamWithDefaultValue( |
| 246 variation_params, "correlation_logging_probability", 0.0); |
| 247 DCHECK_LE(0.0, correlation_uma_logging_probability); |
| 248 DCHECK_GE(1.0, correlation_uma_logging_probability); |
| 249 return correlation_uma_logging_probability; |
| 250 } |
| 251 |
| 252 bool forced_effective_connection_type_set( |
| 253 const std::map<std::string, std::string>& variation_params) { |
| 254 return !GetStringValueForVariationParamWithDefaultValue( |
| 255 variation_params, "force_effective_connection_type", "") |
| 256 .empty(); |
| 257 } |
| 258 |
| 259 EffectiveConnectionType forced_effective_connection_type( |
| 260 const std::map<std::string, std::string>& variation_params) { |
| 261 EffectiveConnectionType forced_effective_connection_type = |
| 262 EFFECTIVE_CONNECTION_TYPE_UNKNOWN; |
| 263 std::string forced_value = GetStringValueForVariationParamWithDefaultValue( |
| 264 variation_params, "force_effective_connection_type", |
| 265 GetNameForEffectiveConnectionType(EFFECTIVE_CONNECTION_TYPE_UNKNOWN)); |
| 266 DCHECK(!forced_value.empty()); |
| 267 bool effective_connection_type_available = GetEffectiveConnectionTypeForName( |
| 268 forced_value, &forced_effective_connection_type); |
| 269 DCHECK(effective_connection_type_available); |
| 270 |
| 271 // Silence unused variable warning in release builds. |
| 272 (void)effective_connection_type_available; |
| 273 |
| 274 return forced_effective_connection_type; |
| 275 } |
| 276 |
| 277 } // namespace internal |
| 278 |
| 279 } // namespace nqe |
| 280 |
| 281 } // namespace net |
| OLD | NEW |