| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "base/metrics/field_trial.h" | 5 #include "base/metrics/field_trial.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/build_time.h" | 9 #include "base/build_time.h" |
| 10 #include "base/lazy_instance.h" | 10 #include "base/lazy_instance.h" |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 122 // might be multiple FieldTrialList objects. | 122 // might be multiple FieldTrialList objects. |
| 123 // TODO(asvitkine): Remove when crbug.com/359406 is resolved. | 123 // TODO(asvitkine): Remove when crbug.com/359406 is resolved. |
| 124 base::LazyInstance<std::map<std::string, std::string>>::Leaky g_seen_states = | 124 base::LazyInstance<std::map<std::string, std::string>>::Leaky g_seen_states = |
| 125 LAZY_INSTANCE_INITIALIZER; | 125 LAZY_INSTANCE_INITIALIZER; |
| 126 | 126 |
| 127 // A debug token generated during FieldTrialList construction. Used to diagnose | 127 // A debug token generated during FieldTrialList construction. Used to diagnose |
| 128 // crbug.com/359406. | 128 // crbug.com/359406. |
| 129 // TODO(asvitkine): Remove when crbug.com/359406 is resolved. | 129 // TODO(asvitkine): Remove when crbug.com/359406 is resolved. |
| 130 int32_t g_debug_token = -1; | 130 int32_t g_debug_token = -1; |
| 131 | 131 |
| 132 // Whether to append the debug token to the child process --force-fieldtrials |
| 133 // command line. Used to diagnose crbug.com/359406. |
| 134 // TODO(asvitkine): Remove when crbug.com/359406 is resolved. |
| 135 bool g_append_debug_token_to_trial_string = false; |
| 136 |
| 132 // Tracks whether |g_seen_states| is used. Defaults to false, because unit tests | 137 // Tracks whether |g_seen_states| is used. Defaults to false, because unit tests |
| 133 // will create multiple FieldTrialList instances. Also controls whether | 138 // will create multiple FieldTrialList instances. Also controls whether |
| 134 // |g_debug_token| is included in the field trial state string. | 139 // |g_debug_token| is included in the field trial state string. |
| 135 bool g_use_global_check_states = false; | 140 bool g_use_global_check_states = false; |
| 136 | 141 |
| 137 } // namespace | 142 } // namespace |
| 138 | 143 |
| 139 // statics | 144 // statics |
| 140 const int FieldTrial::kNotFinalized = -1; | 145 const int FieldTrial::kNotFinalized = -1; |
| 141 const int FieldTrial::kDefaultGroupNumber = 0; | 146 const int FieldTrial::kDefaultGroupNumber = 0; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 230 if (forced_) | 235 if (forced_) |
| 231 return; | 236 return; |
| 232 | 237 |
| 233 // And we must finalize the group choice before we mark ourselves as forced. | 238 // And we must finalize the group choice before we mark ourselves as forced. |
| 234 FinalizeGroupChoice(); | 239 FinalizeGroupChoice(); |
| 235 forced_ = true; | 240 forced_ = true; |
| 236 } | 241 } |
| 237 | 242 |
| 238 // static | 243 // static |
| 239 void FieldTrial::EnableBenchmarking() { | 244 void FieldTrial::EnableBenchmarking() { |
| 240 DCHECK_EQ(0u, FieldTrialList::GetFieldTrialCount()); | 245 // TODO(asvitkine): Change this back to 0u after the trial in FieldTrialList |
| 246 // constructor is removed. |
| 247 DCHECK_EQ(1u, FieldTrialList::GetFieldTrialCount()); |
| 241 enable_benchmarking_ = true; | 248 enable_benchmarking_ = true; |
| 242 } | 249 } |
| 243 | 250 |
| 244 // static | 251 // static |
| 245 FieldTrial* FieldTrial::CreateSimulatedFieldTrial( | 252 FieldTrial* FieldTrial::CreateSimulatedFieldTrial( |
| 246 const std::string& trial_name, | 253 const std::string& trial_name, |
| 247 Probability total_probability, | 254 Probability total_probability, |
| 248 const std::string& default_group_name, | 255 const std::string& default_group_name, |
| 249 double entropy_value) { | 256 double entropy_value) { |
| 250 return new FieldTrial(trial_name, total_probability, default_group_name, | 257 return new FieldTrial(trial_name, total_probability, default_group_name, |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 339 ObserverListBase<FieldTrialList::Observer>::NOTIFY_EXISTING_ONLY)) { | 346 ObserverListBase<FieldTrialList::Observer>::NOTIFY_EXISTING_ONLY)) { |
| 340 // TODO(asvitkine): Turn into a DCHECK after http://crbug.com/359406 is fixed. | 347 // TODO(asvitkine): Turn into a DCHECK after http://crbug.com/359406 is fixed. |
| 341 CHECK(!global_); | 348 CHECK(!global_); |
| 342 DCHECK(!used_without_global_); | 349 DCHECK(!used_without_global_); |
| 343 global_ = this; | 350 global_ = this; |
| 344 | 351 |
| 345 Time two_years_from_build_time = GetBuildTime() + TimeDelta::FromDays(730); | 352 Time two_years_from_build_time = GetBuildTime() + TimeDelta::FromDays(730); |
| 346 Time::Exploded exploded; | 353 Time::Exploded exploded; |
| 347 two_years_from_build_time.LocalExplode(&exploded); | 354 two_years_from_build_time.LocalExplode(&exploded); |
| 348 kNoExpirationYear = exploded.year; | 355 kNoExpirationYear = exploded.year; |
| 356 |
| 357 // Run a 50/50 experiment that enables |g_use_global_check_states| only for |
| 358 // half the users, to investigate if this instrumentation is causing the |
| 359 // crashes to disappear for http://crbug.com/359406. Done here instead of a |
| 360 // server-side trial because this needs to be done early during FieldTrialList |
| 361 // initialization. |
| 362 // |
| 363 // Note: |g_use_global_check_states| is set via EnableGlobalStateChecks() |
| 364 // prior to the FieldTrialList being created. We only want to do the trial |
| 365 // check once the first time FieldTrialList is created, so use a static |
| 366 // |first_time| variable to track this. |
| 367 // |
| 368 // TODO(asvitkine): Remove after http://crbug.com/359406 is fixed. |
| 369 static bool first_time = true; |
| 370 if (first_time && g_use_global_check_states) { |
| 371 first_time = false; |
| 372 base::FieldTrial* trial = |
| 373 FactoryGetFieldTrial("UMA_CheckStates", 100, "NoChecks", |
| 374 kNoExpirationYear, 1, 1, |
| 375 FieldTrial::SESSION_RANDOMIZED, nullptr); |
| 376 trial->AppendGroup("Checks", 50); |
| 377 if (trial->group_name() == "NoChecks") |
| 378 g_use_global_check_states = false; |
| 379 } |
| 349 } | 380 } |
| 350 | 381 |
| 351 FieldTrialList::~FieldTrialList() { | 382 FieldTrialList::~FieldTrialList() { |
| 352 AutoLock auto_lock(lock_); | 383 AutoLock auto_lock(lock_); |
| 353 while (!registered_.empty()) { | 384 while (!registered_.empty()) { |
| 354 RegistrationMap::iterator it = registered_.begin(); | 385 RegistrationMap::iterator it = registered_.begin(); |
| 355 it->second->Release(); | 386 it->second->Release(); |
| 356 registered_.erase(it->first); | 387 registered_.erase(it->first); |
| 357 } | 388 } |
| 358 DCHECK_EQ(this, global_); | 389 DCHECK_EQ(this, global_); |
| 359 global_ = NULL; | 390 global_ = NULL; |
| 360 } | 391 } |
| 361 | 392 |
| 362 // static | 393 // static |
| 363 void FieldTrialList::EnableGlobalStateChecks() { | 394 void FieldTrialList::EnableGlobalStateChecks() { |
| 364 CHECK(!g_use_global_check_states); | 395 CHECK(!g_use_global_check_states); |
| 365 g_use_global_check_states = true; | 396 g_use_global_check_states = true; |
| 397 g_append_debug_token_to_trial_string = true; |
| 366 } | 398 } |
| 367 | 399 |
| 368 // static | 400 // static |
| 369 int32_t FieldTrialList::GetDebugToken() { | 401 int32_t FieldTrialList::GetDebugToken() { |
| 370 return g_debug_token; | 402 return g_debug_token; |
| 371 } | 403 } |
| 372 | 404 |
| 373 // static | 405 // static |
| 374 FieldTrial* FieldTrialList::FactoryGetFieldTrial( | 406 FieldTrial* FieldTrialList::FactoryGetFieldTrial( |
| 375 const std::string& trial_name, | 407 const std::string& trial_name, |
| (...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 492 it != active_groups.end(); ++it) { | 524 it != active_groups.end(); ++it) { |
| 493 DCHECK_EQ(std::string::npos, | 525 DCHECK_EQ(std::string::npos, |
| 494 it->trial_name.find(kPersistentStringSeparator)); | 526 it->trial_name.find(kPersistentStringSeparator)); |
| 495 DCHECK_EQ(std::string::npos, | 527 DCHECK_EQ(std::string::npos, |
| 496 it->group_name.find(kPersistentStringSeparator)); | 528 it->group_name.find(kPersistentStringSeparator)); |
| 497 output->append(it->trial_name); | 529 output->append(it->trial_name); |
| 498 output->append(1, kPersistentStringSeparator); | 530 output->append(1, kPersistentStringSeparator); |
| 499 output->append(it->group_name); | 531 output->append(it->group_name); |
| 500 output->append(1, kPersistentStringSeparator); | 532 output->append(1, kPersistentStringSeparator); |
| 501 } | 533 } |
| 502 if (g_use_global_check_states) { | 534 if (g_append_debug_token_to_trial_string) { |
| 503 output->append("DebugToken"); | 535 output->append("DebugToken"); |
| 504 output->append(1, kPersistentStringSeparator); | 536 output->append(1, kPersistentStringSeparator); |
| 505 output->append(IntToString(g_debug_token)); | 537 output->append(IntToString(g_debug_token)); |
| 506 output->append(1, kPersistentStringSeparator); | 538 output->append(1, kPersistentStringSeparator); |
| 507 } | 539 } |
| 508 } | 540 } |
| 509 | 541 |
| 510 // static | 542 // static |
| 511 void FieldTrialList::AllStatesToString(std::string* output) { | 543 void FieldTrialList::AllStatesToString(std::string* output) { |
| 512 if (!global_) | 544 if (!global_) |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 return; | 739 return; |
| 708 } | 740 } |
| 709 AutoLock auto_lock(global_->lock_); | 741 AutoLock auto_lock(global_->lock_); |
| 710 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 742 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
| 711 trial->AddRef(); | 743 trial->AddRef(); |
| 712 trial->SetTrialRegistered(); | 744 trial->SetTrialRegistered(); |
| 713 global_->registered_[trial->trial_name()] = trial; | 745 global_->registered_[trial->trial_name()] = trial; |
| 714 } | 746 } |
| 715 | 747 |
| 716 } // namespace base | 748 } // namespace base |
| OLD | NEW |