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 |