OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2012 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 "chrome/browser/chrome_browser_field_trials.h" |
| 6 |
| 7 #include <string> |
| 8 |
| 9 #include "base/command_line.h" |
| 10 #include "base/metrics/field_trial.h" |
| 11 #include "base/string_number_conversions.h" |
| 12 #include "base/string_util.h" |
| 13 #include "base/stringprintf.h" |
| 14 #include "base/sys_string_conversions.h" |
| 15 #include "base/utf_string_conversions.h" |
| 16 #include "chrome/browser/auto_launch_trial.h" |
| 17 #include "chrome/browser/autocomplete/autocomplete_field_trial.h" |
| 18 #include "chrome/browser/extensions/default_apps_trial.h" |
| 19 #include "chrome/browser/google/google_util.h" |
| 20 #include "chrome/browser/gpu_util.h" |
| 21 #include "chrome/browser/net/predictor.h" |
| 22 #include "chrome/browser/prerender/prerender_field_trial.h" |
| 23 #include "chrome/common/chrome_switches.h" |
| 24 #include "chrome/common/chrome_version_info.h" |
| 25 #include "chrome/common/metrics/experiments_helper.h" |
| 26 #include "net/http/http_network_layer.h" |
| 27 #include "net/http/http_stream_factory.h" |
| 28 #include "net/socket/client_socket_pool_base.h" |
| 29 #include "net/socket/client_socket_pool_manager.h" |
| 30 #include "net/spdy/spdy_session.h" |
| 31 #include "net/spdy/spdy_session_pool.h" |
| 32 #include "ui/base/layout.h" |
| 33 |
| 34 #if defined(OS_WIN) |
| 35 #include "ui/base/win/dpi.h" // For DisableNewTabFieldTrialIfNecesssary. |
| 36 #endif // defined(OS_WIN) |
| 37 |
| 38 namespace { |
| 39 |
| 40 // Set up a uniformity field trial. |one_time_randomized| indicates if the |
| 41 // field trial is one-time randomized or session-randomized. |trial_name_string| |
| 42 // must contain a "%d" since the percentage of the group will be inserted in |
| 43 // the trial name. |num_trial_groups| must be a divisor of 100 (e.g. 5, 20) |
| 44 void SetupSingleUniformityFieldTrial( |
| 45 bool one_time_randomized, |
| 46 const std::string& trial_name_string, |
| 47 const chrome_variations::VariationID trial_base_id, |
| 48 int num_trial_groups) { |
| 49 // Probability per group remains constant for all uniformity trials, what |
| 50 // changes is the probability divisor. |
| 51 static const base::FieldTrial::Probability kProbabilityPerGroup = 1; |
| 52 const std::string kDefaultGroupName = "default"; |
| 53 const base::FieldTrial::Probability divisor = num_trial_groups; |
| 54 |
| 55 DCHECK_EQ(100 % num_trial_groups, 0); |
| 56 const int group_percent = 100 / num_trial_groups; |
| 57 const std::string trial_name = StringPrintf(trial_name_string.c_str(), |
| 58 group_percent); |
| 59 |
| 60 DVLOG(1) << "Trial name = " << trial_name; |
| 61 |
| 62 scoped_refptr<base::FieldTrial> trial( |
| 63 base::FieldTrialList::FactoryGetFieldTrial( |
| 64 trial_name, divisor, kDefaultGroupName, 2015, 1, 1, NULL)); |
| 65 if (one_time_randomized) |
| 66 trial->UseOneTimeRandomization(); |
| 67 experiments_helper::AssociateGoogleVariationID(trial_name, kDefaultGroupName, |
| 68 trial_base_id); |
| 69 // Loop starts with group 1 because the field trial automatically creates a |
| 70 // default group, which would be group 0. |
| 71 for (int group_number = 1; group_number < num_trial_groups; ++group_number) { |
| 72 const std::string group_name = StringPrintf("group_%02d", group_number); |
| 73 DVLOG(1) << " Group name = " << group_name; |
| 74 trial->AppendGroup(group_name, kProbabilityPerGroup); |
| 75 experiments_helper::AssociateGoogleVariationID(trial_name, group_name, |
| 76 static_cast<chrome_variations::VariationID>(trial_base_id + |
| 77 group_number)); |
| 78 } |
| 79 |
| 80 // Now that all groups have been appended, call group() on the trial to |
| 81 // ensure that our trial is registered. This resolves an off-by-one issue |
| 82 // where the default group never gets chosen if we don't "use" the trial. |
| 83 const int chosen_group = trial->group(); |
| 84 DVLOG(1) << "Chosen Group: " << chosen_group; |
| 85 } |
| 86 |
| 87 void SetSocketReusePolicy(int warmest_socket_trial_group, |
| 88 const int socket_policy[], |
| 89 int num_groups) { |
| 90 const int* result = std::find(socket_policy, socket_policy + num_groups, |
| 91 warmest_socket_trial_group); |
| 92 DCHECK_NE(result, socket_policy + num_groups) |
| 93 << "Not a valid socket reuse policy group"; |
| 94 net::SetSocketReusePolicy(result - socket_policy); |
| 95 } |
| 96 |
| 97 } // namespace |
| 98 |
| 99 ChromeBrowserFieldTrials::ChromeBrowserFieldTrials( |
| 100 const CommandLine& parsed_command_line) : |
| 101 parsed_command_line_(parsed_command_line) { |
| 102 } |
| 103 |
| 104 ChromeBrowserFieldTrials::~ChromeBrowserFieldTrials() { |
| 105 } |
| 106 |
| 107 void ChromeBrowserFieldTrials::SetupFieldTrials(bool proxy_policy_is_set) { |
| 108 // Note: make sure to call ConnectionFieldTrial() before |
| 109 // ProxyConnectionsFieldTrial(). |
| 110 ConnectionFieldTrial(); |
| 111 SocketTimeoutFieldTrial(); |
| 112 // If a policy is defining the number of active connections this field test |
| 113 // shoud not be performed. |
| 114 if (!proxy_policy_is_set) |
| 115 ProxyConnectionsFieldTrial(); |
| 116 prerender::ConfigurePrefetchAndPrerender(parsed_command_line_); |
| 117 SpdyFieldTrial(); |
| 118 ConnectBackupJobsFieldTrial(); |
| 119 WarmConnectionFieldTrial(); |
| 120 PredictorFieldTrial(); |
| 121 DefaultAppsFieldTrial(); |
| 122 AutoLaunchChromeFieldTrial(); |
| 123 gpu_util::InitializeForceCompositingModeFieldTrial(); |
| 124 SetupUniformityFieldTrials(); |
| 125 AutocompleteFieldTrial::Activate(); |
| 126 DisableNewTabFieldTrialIfNecesssary(); |
| 127 ChannelIDFieldTrial(); |
| 128 } |
| 129 |
| 130 // This is an A/B test for the maximum number of persistent connections per |
| 131 // host. Currently Chrome, Firefox, and IE8 have this value set at 6. Safari |
| 132 // uses 4, and Fasterfox (a plugin for Firefox that supposedly configures it to |
| 133 // run faster) uses 8. We would like to see how much of an effect this value has |
| 134 // on browsing. Too large a value might cause us to run into SYN flood detection |
| 135 // mechanisms. |
| 136 void ChromeBrowserFieldTrials::ConnectionFieldTrial() { |
| 137 const base::FieldTrial::Probability kConnectDivisor = 100; |
| 138 const base::FieldTrial::Probability kConnectProbability = 1; // 1% prob. |
| 139 |
| 140 // This (6) is the current default value. Having this group declared here |
| 141 // makes it straightforward to modify |kConnectProbability| such that the same |
| 142 // probability value will be assigned to all the other groups, while |
| 143 // preserving the remainder of the of probability space to the default value. |
| 144 int connect_6 = -1; |
| 145 |
| 146 // After June 30, 2011 builds, it will always be in default group. |
| 147 scoped_refptr<base::FieldTrial> connect_trial( |
| 148 base::FieldTrialList::FactoryGetFieldTrial( |
| 149 "ConnCountImpact", kConnectDivisor, "conn_count_6", 2011, 6, 30, |
| 150 &connect_6)); |
| 151 |
| 152 const int connect_5 = connect_trial->AppendGroup("conn_count_5", |
| 153 kConnectProbability); |
| 154 const int connect_7 = connect_trial->AppendGroup("conn_count_7", |
| 155 kConnectProbability); |
| 156 const int connect_8 = connect_trial->AppendGroup("conn_count_8", |
| 157 kConnectProbability); |
| 158 const int connect_9 = connect_trial->AppendGroup("conn_count_9", |
| 159 kConnectProbability); |
| 160 |
| 161 const int connect_trial_group = connect_trial->group(); |
| 162 |
| 163 int max_sockets = 0; |
| 164 if (connect_trial_group == connect_5) { |
| 165 max_sockets = 5; |
| 166 } else if (connect_trial_group == connect_6) { |
| 167 max_sockets = 6; |
| 168 } else if (connect_trial_group == connect_7) { |
| 169 max_sockets = 7; |
| 170 } else if (connect_trial_group == connect_8) { |
| 171 max_sockets = 8; |
| 172 } else if (connect_trial_group == connect_9) { |
| 173 max_sockets = 9; |
| 174 } else { |
| 175 NOTREACHED(); |
| 176 } |
| 177 net::ClientSocketPoolManager::set_max_sockets_per_group( |
| 178 net::HttpNetworkSession::NORMAL_SOCKET_POOL, max_sockets); |
| 179 } |
| 180 |
| 181 // A/B test for determining a value for unused socket timeout. Currently the |
| 182 // timeout defaults to 10 seconds. Having this value set too low won't allow us |
| 183 // to take advantage of idle sockets. Setting it to too high could possibly |
| 184 // result in more ERR_CONNECTION_RESETs, since some servers will kill a socket |
| 185 // before we time it out. Since these are "unused" sockets, we won't retry the |
| 186 // connection and instead show an error to the user. So we need to be |
| 187 // conservative here. We've seen that some servers will close the socket after |
| 188 // as short as 10 seconds. See http://crbug.com/84313 for more details. |
| 189 void ChromeBrowserFieldTrials::SocketTimeoutFieldTrial() { |
| 190 const base::FieldTrial::Probability kIdleSocketTimeoutDivisor = 100; |
| 191 // 1% probability for all experimental settings. |
| 192 const base::FieldTrial::Probability kSocketTimeoutProbability = 1; |
| 193 |
| 194 // After June 30, 2011 builds, it will always be in default group. |
| 195 int socket_timeout_10 = -1; |
| 196 scoped_refptr<base::FieldTrial> socket_timeout_trial( |
| 197 base::FieldTrialList::FactoryGetFieldTrial( |
| 198 "IdleSktToImpact", kIdleSocketTimeoutDivisor, "idle_timeout_10", |
| 199 2011, 6, 30, &socket_timeout_10)); |
| 200 |
| 201 const int socket_timeout_5 = |
| 202 socket_timeout_trial->AppendGroup("idle_timeout_5", |
| 203 kSocketTimeoutProbability); |
| 204 const int socket_timeout_20 = |
| 205 socket_timeout_trial->AppendGroup("idle_timeout_20", |
| 206 kSocketTimeoutProbability); |
| 207 |
| 208 const int idle_to_trial_group = socket_timeout_trial->group(); |
| 209 |
| 210 if (idle_to_trial_group == socket_timeout_5) { |
| 211 net::ClientSocketPool::set_unused_idle_socket_timeout( |
| 212 base::TimeDelta::FromSeconds(5)); |
| 213 } else if (idle_to_trial_group == socket_timeout_10) { |
| 214 net::ClientSocketPool::set_unused_idle_socket_timeout( |
| 215 base::TimeDelta::FromSeconds(10)); |
| 216 } else if (idle_to_trial_group == socket_timeout_20) { |
| 217 net::ClientSocketPool::set_unused_idle_socket_timeout( |
| 218 base::TimeDelta::FromSeconds(20)); |
| 219 } else { |
| 220 NOTREACHED(); |
| 221 } |
| 222 } |
| 223 |
| 224 void ChromeBrowserFieldTrials::ProxyConnectionsFieldTrial() { |
| 225 const base::FieldTrial::Probability kProxyConnectionsDivisor = 100; |
| 226 // 25% probability |
| 227 const base::FieldTrial::Probability kProxyConnectionProbability = 1; |
| 228 |
| 229 // This (32 connections per proxy server) is the current default value. |
| 230 // Declaring it here allows us to easily re-assign the probability space while |
| 231 // maintaining that the default group always has the remainder of the "share", |
| 232 // which allows for cleaner and quicker changes down the line if needed. |
| 233 int proxy_connections_32 = -1; |
| 234 |
| 235 // After June 30, 2011 builds, it will always be in default group. |
| 236 scoped_refptr<base::FieldTrial> proxy_connection_trial( |
| 237 base::FieldTrialList::FactoryGetFieldTrial( |
| 238 "ProxyConnectionImpact", kProxyConnectionsDivisor, |
| 239 "proxy_connections_32", 2011, 6, 30, &proxy_connections_32)); |
| 240 |
| 241 // The number of max sockets per group cannot be greater than the max number |
| 242 // of sockets per proxy server. We tried using 8, and it can easily |
| 243 // lead to total browser stalls. |
| 244 const int proxy_connections_16 = |
| 245 proxy_connection_trial->AppendGroup("proxy_connections_16", |
| 246 kProxyConnectionProbability); |
| 247 const int proxy_connections_64 = |
| 248 proxy_connection_trial->AppendGroup("proxy_connections_64", |
| 249 kProxyConnectionProbability); |
| 250 |
| 251 const int proxy_connections_trial_group = proxy_connection_trial->group(); |
| 252 |
| 253 int max_sockets = 0; |
| 254 if (proxy_connections_trial_group == proxy_connections_16) { |
| 255 max_sockets = 16; |
| 256 } else if (proxy_connections_trial_group == proxy_connections_32) { |
| 257 max_sockets = 32; |
| 258 } else if (proxy_connections_trial_group == proxy_connections_64) { |
| 259 max_sockets = 64; |
| 260 } else { |
| 261 NOTREACHED(); |
| 262 } |
| 263 net::ClientSocketPoolManager::set_max_sockets_per_proxy_server( |
| 264 net::HttpNetworkSession::NORMAL_SOCKET_POOL, max_sockets); |
| 265 } |
| 266 |
| 267 // When --use-spdy not set, users will be in A/B test for spdy. |
| 268 // group A (npn_with_spdy): this means npn and spdy are enabled. In case server |
| 269 // supports spdy, browser will use spdy. |
| 270 // group B (npn_with_http): this means npn is enabled but spdy won't be used. |
| 271 // Http is still used for all requests. |
| 272 // default group: no npn or spdy is involved. The "old" non-spdy |
| 273 // chrome behavior. |
| 274 void ChromeBrowserFieldTrials::SpdyFieldTrial() { |
| 275 bool use_field_trial = true; |
| 276 if (parsed_command_line_.HasSwitch(switches::kUseSpdy)) { |
| 277 std::string spdy_mode = |
| 278 parsed_command_line_.GetSwitchValueASCII(switches::kUseSpdy); |
| 279 net::HttpNetworkLayer::EnableSpdy(spdy_mode); |
| 280 use_field_trial = false; |
| 281 } |
| 282 if (parsed_command_line_.HasSwitch(switches::kEnableSpdy3)) { |
| 283 net::HttpStreamFactory::EnableNpnSpdy3(); |
| 284 use_field_trial = false; |
| 285 } else if (parsed_command_line_.HasSwitch(switches::kEnableNpn)) { |
| 286 net::HttpStreamFactory::EnableNpnSpdy(); |
| 287 use_field_trial = false; |
| 288 } else if (parsed_command_line_.HasSwitch(switches::kEnableNpnHttpOnly)) { |
| 289 net::HttpStreamFactory::EnableNpnHttpOnly(); |
| 290 use_field_trial = false; |
| 291 } |
| 292 if (use_field_trial) { |
| 293 const base::FieldTrial::Probability kSpdyDivisor = 100; |
| 294 // Enable SPDY/3 for 95% of the users, HTTP (no SPDY) for 1% of the users |
| 295 // and SPDY/2 for 4% of the users. |
| 296 base::FieldTrial::Probability npnhttp_probability = 1; |
| 297 base::FieldTrial::Probability spdy3_probability = 95; |
| 298 |
| 299 #if defined(OS_CHROMEOS) |
| 300 // Always enable SPDY (spdy/2 or spdy/3) on Chrome OS |
| 301 npnhttp_probability = 0; |
| 302 #endif // !defined(OS_CHROMEOS) |
| 303 |
| 304 // NPN with spdy support is the default. |
| 305 int npn_spdy_grp = -1; |
| 306 |
| 307 // After June 30, 2013 builds, it will always be in default group. |
| 308 scoped_refptr<base::FieldTrial> trial( |
| 309 base::FieldTrialList::FactoryGetFieldTrial( |
| 310 "SpdyImpact", kSpdyDivisor, "npn_with_spdy", 2013, 6, 30, |
| 311 &npn_spdy_grp)); |
| 312 |
| 313 // NPN with only http support, no spdy. |
| 314 int npn_http_grp = trial->AppendGroup("npn_with_http", npnhttp_probability); |
| 315 |
| 316 // NPN with http/1.1, spdy/2, and spdy/3 support. |
| 317 int spdy3_grp = trial->AppendGroup("spdy3", spdy3_probability); |
| 318 |
| 319 int trial_grp = trial->group(); |
| 320 if (trial_grp == npn_spdy_grp) { |
| 321 net::HttpStreamFactory::EnableNpnSpdy(); |
| 322 } else if (trial_grp == npn_http_grp) { |
| 323 net::HttpStreamFactory::EnableNpnHttpOnly(); |
| 324 } else if (trial_grp == spdy3_grp) { |
| 325 net::HttpStreamFactory::EnableNpnSpdy3(); |
| 326 } else { |
| 327 NOTREACHED(); |
| 328 } |
| 329 } |
| 330 |
| 331 // Setup SPDY CWND Field trial. |
| 332 const base::FieldTrial::Probability kSpdyCwndDivisor = 100; |
| 333 const base::FieldTrial::Probability kSpdyCwnd16 = 20; // fixed at 16 |
| 334 const base::FieldTrial::Probability kSpdyCwnd10 = 20; // fixed at 10 |
| 335 const base::FieldTrial::Probability kSpdyCwndMin16 = 20; // no less than 16 |
| 336 const base::FieldTrial::Probability kSpdyCwndMin10 = 20; // no less than 10 |
| 337 |
| 338 // After June 30, 2013 builds, it will always be in default group |
| 339 // (cwndDynamic). |
| 340 scoped_refptr<base::FieldTrial> trial( |
| 341 base::FieldTrialList::FactoryGetFieldTrial( |
| 342 "SpdyCwnd", kSpdyCwndDivisor, "cwndDynamic", 2013, 6, 30, NULL)); |
| 343 |
| 344 trial->AppendGroup("cwnd10", kSpdyCwnd10); |
| 345 trial->AppendGroup("cwnd16", kSpdyCwnd16); |
| 346 trial->AppendGroup("cwndMin16", kSpdyCwndMin16); |
| 347 trial->AppendGroup("cwndMin10", kSpdyCwndMin10); |
| 348 |
| 349 if (parsed_command_line_.HasSwitch(switches::kMaxSpdyConcurrentStreams)) { |
| 350 int value = 0; |
| 351 base::StringToInt(parsed_command_line_.GetSwitchValueASCII( |
| 352 switches::kMaxSpdyConcurrentStreams), |
| 353 &value); |
| 354 if (value > 0) |
| 355 net::SpdySession::set_max_concurrent_streams(value); |
| 356 } |
| 357 } |
| 358 |
| 359 // If --socket-reuse-policy is not specified, run an A/B test for choosing the |
| 360 // warmest socket. |
| 361 void ChromeBrowserFieldTrials::WarmConnectionFieldTrial() { |
| 362 const CommandLine& command_line = parsed_command_line_; |
| 363 if (command_line.HasSwitch(switches::kSocketReusePolicy)) { |
| 364 std::string socket_reuse_policy_str = command_line.GetSwitchValueASCII( |
| 365 switches::kSocketReusePolicy); |
| 366 int policy = -1; |
| 367 base::StringToInt(socket_reuse_policy_str, &policy); |
| 368 |
| 369 const int policy_list[] = { 0, 1, 2 }; |
| 370 VLOG(1) << "Setting socket_reuse_policy = " << policy; |
| 371 SetSocketReusePolicy(policy, policy_list, arraysize(policy_list)); |
| 372 return; |
| 373 } |
| 374 |
| 375 const base::FieldTrial::Probability kWarmSocketDivisor = 100; |
| 376 const base::FieldTrial::Probability kWarmSocketProbability = 33; |
| 377 |
| 378 // Default value is USE_LAST_ACCESSED_SOCKET. |
| 379 int last_accessed_socket = -1; |
| 380 |
| 381 // After January 30, 2013 builds, it will always be in default group. |
| 382 scoped_refptr<base::FieldTrial> warmest_socket_trial( |
| 383 base::FieldTrialList::FactoryGetFieldTrial( |
| 384 "WarmSocketImpact", kWarmSocketDivisor, "last_accessed_socket", |
| 385 2013, 1, 30, &last_accessed_socket)); |
| 386 |
| 387 const int warmest_socket = warmest_socket_trial->AppendGroup( |
| 388 "warmest_socket", kWarmSocketProbability); |
| 389 const int warm_socket = warmest_socket_trial->AppendGroup( |
| 390 "warm_socket", kWarmSocketProbability); |
| 391 |
| 392 const int warmest_socket_trial_group = warmest_socket_trial->group(); |
| 393 |
| 394 const int policy_list[] = { warmest_socket, warm_socket, |
| 395 last_accessed_socket }; |
| 396 SetSocketReusePolicy(warmest_socket_trial_group, policy_list, |
| 397 arraysize(policy_list)); |
| 398 } |
| 399 |
| 400 // If neither --enable-connect-backup-jobs or --disable-connect-backup-jobs is |
| 401 // specified, run an A/B test for automatically establishing backup TCP |
| 402 // connections when a certain timeout value is exceeded. |
| 403 void ChromeBrowserFieldTrials::ConnectBackupJobsFieldTrial() { |
| 404 if (parsed_command_line_.HasSwitch(switches::kEnableConnectBackupJobs)) { |
| 405 net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled( |
| 406 true); |
| 407 } else if (parsed_command_line_.HasSwitch( |
| 408 switches::kDisableConnectBackupJobs)) { |
| 409 net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled( |
| 410 false); |
| 411 } else { |
| 412 const base::FieldTrial::Probability kConnectBackupJobsDivisor = 100; |
| 413 // 1% probability. |
| 414 const base::FieldTrial::Probability kConnectBackupJobsProbability = 1; |
| 415 // After June 30, 2011 builds, it will always be in default group. |
| 416 int connect_backup_jobs_enabled = -1; |
| 417 scoped_refptr<base::FieldTrial> trial( |
| 418 base::FieldTrialList::FactoryGetFieldTrial("ConnnectBackupJobs", |
| 419 kConnectBackupJobsDivisor, "ConnectBackupJobsEnabled", |
| 420 2011, 6, 30, &connect_backup_jobs_enabled)); |
| 421 trial->AppendGroup("ConnectBackupJobsDisabled", |
| 422 kConnectBackupJobsProbability); |
| 423 const int trial_group = trial->group(); |
| 424 net::internal::ClientSocketPoolBaseHelper::set_connect_backup_jobs_enabled( |
| 425 trial_group == connect_backup_jobs_enabled); |
| 426 } |
| 427 } |
| 428 |
| 429 void ChromeBrowserFieldTrials::PredictorFieldTrial() { |
| 430 const base::FieldTrial::Probability kDivisor = 1000; |
| 431 // For each option (i.e., non-default), we have a fixed probability. |
| 432 // 0.1% probability. |
| 433 const base::FieldTrial::Probability kProbabilityPerGroup = 1; |
| 434 |
| 435 // After June 30, 2011 builds, it will always be in default group |
| 436 // (default_enabled_prefetch). |
| 437 scoped_refptr<base::FieldTrial> trial( |
| 438 base::FieldTrialList::FactoryGetFieldTrial( |
| 439 "DnsImpact", kDivisor, "default_enabled_prefetch", 2011, 10, 30, |
| 440 NULL)); |
| 441 |
| 442 // First option is to disable prefetching completely. |
| 443 int disabled_prefetch = trial->AppendGroup("disabled_prefetch", |
| 444 kProbabilityPerGroup); |
| 445 |
| 446 // We're running two experiments at the same time. The first set of trials |
| 447 // modulates the delay-time until we declare a congestion event (and purge |
| 448 // our queue). The second modulates the number of concurrent resolutions |
| 449 // we do at any time. Users are in exactly one trial (or the default) during |
| 450 // any one run, and hence only one experiment at a time. |
| 451 // Experiment 1: |
| 452 // Set congestion detection at 250, 500, or 750ms, rather than the 1 second |
| 453 // default. |
| 454 int max_250ms_prefetch = trial->AppendGroup("max_250ms_queue_prefetch", |
| 455 kProbabilityPerGroup); |
| 456 int max_500ms_prefetch = trial->AppendGroup("max_500ms_queue_prefetch", |
| 457 kProbabilityPerGroup); |
| 458 int max_750ms_prefetch = trial->AppendGroup("max_750ms_queue_prefetch", |
| 459 kProbabilityPerGroup); |
| 460 // Set congestion detection at 2 seconds instead of the 1 second default. |
| 461 int max_2s_prefetch = trial->AppendGroup("max_2s_queue_prefetch", |
| 462 kProbabilityPerGroup); |
| 463 // Experiment 2: |
| 464 // Set max simultaneous resoultions to 2, 4, or 6, and scale the congestion |
| 465 // limit proportionally (so we don't impact average probability of asserting |
| 466 // congesion very much). |
| 467 int max_2_concurrent_prefetch = trial->AppendGroup( |
| 468 "max_2 concurrent_prefetch", kProbabilityPerGroup); |
| 469 int max_4_concurrent_prefetch = trial->AppendGroup( |
| 470 "max_4 concurrent_prefetch", kProbabilityPerGroup); |
| 471 int max_6_concurrent_prefetch = trial->AppendGroup( |
| 472 "max_6 concurrent_prefetch", kProbabilityPerGroup); |
| 473 |
| 474 if (trial->group() != disabled_prefetch) { |
| 475 // Initialize the DNS prefetch system. |
| 476 size_t max_parallel_resolves = |
| 477 chrome_browser_net::Predictor::kMaxSpeculativeParallelResolves; |
| 478 int max_queueing_delay_ms = |
| 479 chrome_browser_net::Predictor::kMaxSpeculativeResolveQueueDelayMs; |
| 480 |
| 481 if (trial->group() == max_2_concurrent_prefetch) |
| 482 max_parallel_resolves = 2; |
| 483 else if (trial->group() == max_4_concurrent_prefetch) |
| 484 max_parallel_resolves = 4; |
| 485 else if (trial->group() == max_6_concurrent_prefetch) |
| 486 max_parallel_resolves = 6; |
| 487 chrome_browser_net::Predictor::set_max_parallel_resolves( |
| 488 max_parallel_resolves); |
| 489 |
| 490 if (trial->group() == max_250ms_prefetch) { |
| 491 max_queueing_delay_ms = |
| 492 (250 * chrome_browser_net::Predictor::kTypicalSpeculativeGroupSize) / |
| 493 max_parallel_resolves; |
| 494 } else if (trial->group() == max_500ms_prefetch) { |
| 495 max_queueing_delay_ms = |
| 496 (500 * chrome_browser_net::Predictor::kTypicalSpeculativeGroupSize) / |
| 497 max_parallel_resolves; |
| 498 } else if (trial->group() == max_750ms_prefetch) { |
| 499 max_queueing_delay_ms = |
| 500 (750 * chrome_browser_net::Predictor::kTypicalSpeculativeGroupSize) / |
| 501 max_parallel_resolves; |
| 502 } else if (trial->group() == max_2s_prefetch) { |
| 503 max_queueing_delay_ms = |
| 504 (2000 * chrome_browser_net::Predictor::kTypicalSpeculativeGroupSize) / |
| 505 max_parallel_resolves; |
| 506 } |
| 507 chrome_browser_net::Predictor::set_max_queueing_delay( |
| 508 max_queueing_delay_ms); |
| 509 } |
| 510 } |
| 511 |
| 512 void ChromeBrowserFieldTrials::DefaultAppsFieldTrial() { |
| 513 std::string brand; |
| 514 google_util::GetBrand(&brand); |
| 515 |
| 516 // Create a 100% field trial based on the brand code. |
| 517 if (LowerCaseEqualsASCII(brand, "ecdb")) { |
| 518 base::FieldTrialList::CreateFieldTrial(kDefaultAppsTrialName, |
| 519 kDefaultAppsTrialNoAppsGroup); |
| 520 } else if (LowerCaseEqualsASCII(brand, "ecda")) { |
| 521 base::FieldTrialList::CreateFieldTrial(kDefaultAppsTrialName, |
| 522 kDefaultAppsTrialWithAppsGroup); |
| 523 } |
| 524 } |
| 525 |
| 526 void ChromeBrowserFieldTrials::AutoLaunchChromeFieldTrial() { |
| 527 std::string brand; |
| 528 google_util::GetBrand(&brand); |
| 529 |
| 530 // Create a 100% field trial based on the brand code. |
| 531 if (auto_launch_trial::IsInExperimentGroup(brand)) { |
| 532 base::FieldTrialList::CreateFieldTrial(kAutoLaunchTrialName, |
| 533 kAutoLaunchTrialAutoLaunchGroup); |
| 534 } else if (auto_launch_trial::IsInControlGroup(brand)) { |
| 535 base::FieldTrialList::CreateFieldTrial(kAutoLaunchTrialName, |
| 536 kAutoLaunchTrialControlGroup); |
| 537 } |
| 538 } |
| 539 |
| 540 void ChromeBrowserFieldTrials::SetupUniformityFieldTrials() { |
| 541 // One field trial will be created for each entry in this array. The i'th |
| 542 // field trial will have |trial_sizes[i]| groups in it, including the default |
| 543 // group. Each group will have a probability of 1/|trial_sizes[i]|. |
| 544 const int num_trial_groups[] = { 100, 20, 10, 5, 2 }; |
| 545 |
| 546 // Declare our variation ID bases along side this array so we can loop over it |
| 547 // and assign the IDs appropriately. So for example, the 1 percent experiments |
| 548 // should have a size of 100 (100/100 = 1). |
| 549 const chrome_variations::VariationID trial_base_ids[] = { |
| 550 chrome_variations::kUniformity1PercentBase, |
| 551 chrome_variations::kUniformity5PercentBase, |
| 552 chrome_variations::kUniformity10PercentBase, |
| 553 chrome_variations::kUniformity20PercentBase, |
| 554 chrome_variations::kUniformity50PercentBase |
| 555 }; |
| 556 |
| 557 const std::string kOneTimeRandomizedTrialName = |
| 558 "UMA-Uniformity-Trial-%d-Percent"; |
| 559 for (size_t i = 0; i < arraysize(num_trial_groups); ++i) { |
| 560 SetupSingleUniformityFieldTrial(true, kOneTimeRandomizedTrialName, |
| 561 trial_base_ids[i], num_trial_groups[i]); |
| 562 } |
| 563 |
| 564 // Setup a 5% session-randomized uniformity trial. |
| 565 const std::string kSessionRandomizedTrialName = |
| 566 "UMA-Session-Randomized-Uniformity-Trial-%d-Percent"; |
| 567 SetupSingleUniformityFieldTrial(false, kSessionRandomizedTrialName, |
| 568 chrome_variations::kUniformitySessionRandomized5PercentBase, 20); |
| 569 } |
| 570 |
| 571 void ChromeBrowserFieldTrials::DisableNewTabFieldTrialIfNecesssary() { |
| 572 // The new tab button field trial will get created in variations_service.cc |
| 573 // through the variations server. However, since there are no HiDPI assets |
| 574 // for it, disable it for non-desktop layouts. |
| 575 base::FieldTrial* trial = base::FieldTrialList::Find("NewTabButton"); |
| 576 if (trial) { |
| 577 bool using_hidpi_assets = false; |
| 578 #if defined(ENABLE_HIDPI) && defined(OS_WIN) |
| 579 // Mirrors logic in resource_bundle_win.cc. |
| 580 using_hidpi_assets = ui::GetDPIScale() > 1.5; |
| 581 #endif |
| 582 if (ui::GetDisplayLayout() != ui::LAYOUT_DESKTOP || using_hidpi_assets) |
| 583 trial->Disable(); |
| 584 } |
| 585 } |
| 586 |
| 587 void ChromeBrowserFieldTrials::ChannelIDFieldTrial() { |
| 588 chrome::VersionInfo::Channel channel = chrome::VersionInfo::GetChannel(); |
| 589 if (channel == chrome::VersionInfo::CHANNEL_CANARY) { |
| 590 net::SSLConfigService::EnableChannelIDTrial(); |
| 591 } else if (channel == chrome::VersionInfo::CHANNEL_DEV && |
| 592 base::FieldTrialList::IsOneTimeRandomizationEnabled()) { |
| 593 const base::FieldTrial::Probability kDivisor = 100; |
| 594 // 10% probability of being in the enabled group. |
| 595 const base::FieldTrial::Probability kEnableProbability = 10; |
| 596 scoped_refptr<base::FieldTrial> trial = |
| 597 base::FieldTrialList::FactoryGetFieldTrial( |
| 598 "ChannelID", kDivisor, "disable", 2012, 8, 23, NULL); |
| 599 trial->UseOneTimeRandomization(); |
| 600 int enable_group = trial->AppendGroup("enable", kEnableProbability); |
| 601 if (trial->group() == enable_group) |
| 602 net::SSLConfigService::EnableChannelIDTrial(); |
| 603 } |
| 604 } |
OLD | NEW |