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

Side by Side Diff: base/metrics/field_trial.cc

Issue 2024683002: Remove debug instrumentation for crbug.com/359406. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: update render_messages macro Created 4 years, 6 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
« no previous file with comments | « base/metrics/field_trial.h ('k') | chrome/browser/chrome_browser_main.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
11 #include "base/logging.h" 10 #include "base/logging.h"
12 #include "base/rand_util.h" 11 #include "base/rand_util.h"
13 #include "base/strings/string_number_conversions.h" 12 #include "base/strings/string_number_conversions.h"
14 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
15 #include "base/strings/stringprintf.h" 14 #include "base/strings/stringprintf.h"
16 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
17 16
18 namespace base { 17 namespace base {
19 18
20 namespace { 19 namespace {
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 trials_string_piece.substr(next_item, name_end - next_item); 99 trials_string_piece.substr(next_item, name_end - next_item);
101 entry.group_name = 100 entry.group_name =
102 trials_string_piece.substr(name_end + 1, group_name_end - name_end - 1); 101 trials_string_piece.substr(name_end + 1, group_name_end - name_end - 1);
103 next_item = group_name_end + 1; 102 next_item = group_name_end + 1;
104 103
105 entries->push_back(entry); 104 entries->push_back(entry);
106 } 105 }
107 return true; 106 return true;
108 } 107 }
109 108
110 void CheckTrialGroup(const std::string& trial_name,
111 const std::string& trial_group,
112 std::map<std::string, std::string>* seen_states) {
113 if (ContainsKey(*seen_states, trial_name)) {
114 CHECK_EQ((*seen_states)[trial_name], trial_group) << trial_name;
115 } else {
116 (*seen_states)[trial_name] = trial_group;
117 }
118 }
119
120 // A second copy of FieldTrialList::seen_states_ that is meant to outlive the
121 // FieldTrialList object to determine if the inconsistency happens because there
122 // might be multiple FieldTrialList objects.
123 // TODO(asvitkine): Remove when crbug.com/359406 is resolved.
124 base::LazyInstance<std::map<std::string, std::string>>::Leaky g_seen_states =
125 LAZY_INSTANCE_INITIALIZER;
126
127 // A debug token generated during FieldTrialList construction. Used to diagnose
128 // crbug.com/359406.
129 // TODO(asvitkine): Remove when crbug.com/359406 is resolved.
130 int32_t g_debug_token = -1;
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
137 // Tracks whether |g_seen_states| is used. Defaults to false, because unit tests
138 // will create multiple FieldTrialList instances. Also controls whether
139 // |g_debug_token| is included in the field trial state string.
140 bool g_use_global_check_states = false;
141
142 } // namespace 109 } // namespace
143 110
144 // statics 111 // statics
145 const int FieldTrial::kNotFinalized = -1; 112 const int FieldTrial::kNotFinalized = -1;
146 const int FieldTrial::kDefaultGroupNumber = 0; 113 const int FieldTrial::kDefaultGroupNumber = 0;
147 bool FieldTrial::enable_benchmarking_ = false; 114 bool FieldTrial::enable_benchmarking_ = false;
148 115
149 int FieldTrialList::kNoExpirationYear = 0; 116 int FieldTrialList::kNoExpirationYear = 0;
150 117
151 //------------------------------------------------------------------------------ 118 //------------------------------------------------------------------------------
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
235 if (forced_) 202 if (forced_)
236 return; 203 return;
237 204
238 // And we must finalize the group choice before we mark ourselves as forced. 205 // And we must finalize the group choice before we mark ourselves as forced.
239 FinalizeGroupChoice(); 206 FinalizeGroupChoice();
240 forced_ = true; 207 forced_ = true;
241 } 208 }
242 209
243 // static 210 // static
244 void FieldTrial::EnableBenchmarking() { 211 void FieldTrial::EnableBenchmarking() {
245 // TODO(asvitkine): Change this back to 0u after the trial in FieldTrialList 212 DCHECK_EQ(0u, FieldTrialList::GetFieldTrialCount());
246 // constructor is removed.
247 DCHECK_EQ(1u, FieldTrialList::GetFieldTrialCount());
248 enable_benchmarking_ = true; 213 enable_benchmarking_ = true;
249 } 214 }
250 215
251 // static 216 // static
252 FieldTrial* FieldTrial::CreateSimulatedFieldTrial( 217 FieldTrial* FieldTrial::CreateSimulatedFieldTrial(
253 const std::string& trial_name, 218 const std::string& trial_name,
254 Probability total_probability, 219 Probability total_probability,
255 const std::string& default_group_name, 220 const std::string& default_group_name,
256 double entropy_value) { 221 double entropy_value) {
257 return new FieldTrial(trial_name, total_probability, default_group_name, 222 return new FieldTrial(trial_name, total_probability, default_group_name,
(...skipping 11 matching lines...) Expand all
269 accumulated_group_probability_(0), 234 accumulated_group_probability_(0),
270 next_group_number_(kDefaultGroupNumber + 1), 235 next_group_number_(kDefaultGroupNumber + 1),
271 group_(kNotFinalized), 236 group_(kNotFinalized),
272 enable_field_trial_(true), 237 enable_field_trial_(true),
273 forced_(false), 238 forced_(false),
274 group_reported_(false), 239 group_reported_(false),
275 trial_registered_(false) { 240 trial_registered_(false) {
276 DCHECK_GT(total_probability, 0); 241 DCHECK_GT(total_probability, 0);
277 DCHECK(!trial_name_.empty()); 242 DCHECK(!trial_name_.empty());
278 DCHECK(!default_group_name_.empty()); 243 DCHECK(!default_group_name_.empty());
279
280 if (g_debug_token == -1)
281 g_debug_token = RandInt(1, INT32_MAX);
282 } 244 }
283 245
284 FieldTrial::~FieldTrial() {} 246 FieldTrial::~FieldTrial() {}
285 247
286 void FieldTrial::SetTrialRegistered() { 248 void FieldTrial::SetTrialRegistered() {
287 DCHECK_EQ(kNotFinalized, group_); 249 DCHECK_EQ(kNotFinalized, group_);
288 DCHECK(!trial_registered_); 250 DCHECK(!trial_registered_);
289 trial_registered_ = true; 251 trial_registered_ = true;
290 } 252 }
291 253
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
337 bool FieldTrialList::used_without_global_ = false; 299 bool FieldTrialList::used_without_global_ = false;
338 300
339 FieldTrialList::Observer::~Observer() { 301 FieldTrialList::Observer::~Observer() {
340 } 302 }
341 303
342 FieldTrialList::FieldTrialList( 304 FieldTrialList::FieldTrialList(
343 const FieldTrial::EntropyProvider* entropy_provider) 305 const FieldTrial::EntropyProvider* entropy_provider)
344 : entropy_provider_(entropy_provider), 306 : entropy_provider_(entropy_provider),
345 observer_list_(new ObserverListThreadSafe<FieldTrialList::Observer>( 307 observer_list_(new ObserverListThreadSafe<FieldTrialList::Observer>(
346 ObserverListBase<FieldTrialList::Observer>::NOTIFY_EXISTING_ONLY)) { 308 ObserverListBase<FieldTrialList::Observer>::NOTIFY_EXISTING_ONLY)) {
347 // TODO(asvitkine): Turn into a DCHECK after http://crbug.com/359406 is fixed. 309 DCHECK(!global_);
348 CHECK(!global_);
349 DCHECK(!used_without_global_); 310 DCHECK(!used_without_global_);
350 global_ = this; 311 global_ = this;
351 312
352 Time two_years_from_build_time = GetBuildTime() + TimeDelta::FromDays(730); 313 Time two_years_from_build_time = GetBuildTime() + TimeDelta::FromDays(730);
353 Time::Exploded exploded; 314 Time::Exploded exploded;
354 two_years_from_build_time.LocalExplode(&exploded); 315 two_years_from_build_time.LocalExplode(&exploded);
355 kNoExpirationYear = exploded.year; 316 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 }
380 } 317 }
381 318
382 FieldTrialList::~FieldTrialList() { 319 FieldTrialList::~FieldTrialList() {
383 AutoLock auto_lock(lock_); 320 AutoLock auto_lock(lock_);
384 while (!registered_.empty()) { 321 while (!registered_.empty()) {
385 RegistrationMap::iterator it = registered_.begin(); 322 RegistrationMap::iterator it = registered_.begin();
386 it->second->Release(); 323 it->second->Release();
387 registered_.erase(it->first); 324 registered_.erase(it->first);
388 } 325 }
389 DCHECK_EQ(this, global_); 326 DCHECK_EQ(this, global_);
390 global_ = NULL; 327 global_ = NULL;
391 } 328 }
392 329
393 // static 330 // static
394 void FieldTrialList::EnableGlobalStateChecks() {
395 CHECK(!g_use_global_check_states);
396 g_use_global_check_states = true;
397 g_append_debug_token_to_trial_string = true;
398 }
399
400 // static
401 int32_t FieldTrialList::GetDebugToken() {
402 return g_debug_token;
403 }
404
405 // static
406 FieldTrial* FieldTrialList::FactoryGetFieldTrial( 331 FieldTrial* FieldTrialList::FactoryGetFieldTrial(
407 const std::string& trial_name, 332 const std::string& trial_name,
408 FieldTrial::Probability total_probability, 333 FieldTrial::Probability total_probability,
409 const std::string& default_group_name, 334 const std::string& default_group_name,
410 const int year, 335 const int year,
411 const int month, 336 const int month,
412 const int day_of_month, 337 const int day_of_month,
413 FieldTrial::RandomizationType randomization_type, 338 FieldTrial::RandomizationType randomization_type,
414 int* default_group_number) { 339 int* default_group_number) {
415 return FactoryGetFieldTrialWithRandomizationSeed( 340 return FactoryGetFieldTrialWithRandomizationSeed(
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 it != active_groups.end(); ++it) { 452 it != active_groups.end(); ++it) {
528 DCHECK_EQ(std::string::npos, 453 DCHECK_EQ(std::string::npos,
529 it->trial_name.find(kPersistentStringSeparator)); 454 it->trial_name.find(kPersistentStringSeparator));
530 DCHECK_EQ(std::string::npos, 455 DCHECK_EQ(std::string::npos,
531 it->group_name.find(kPersistentStringSeparator)); 456 it->group_name.find(kPersistentStringSeparator));
532 output->append(it->trial_name); 457 output->append(it->trial_name);
533 output->append(1, kPersistentStringSeparator); 458 output->append(1, kPersistentStringSeparator);
534 output->append(it->group_name); 459 output->append(it->group_name);
535 output->append(1, kPersistentStringSeparator); 460 output->append(1, kPersistentStringSeparator);
536 } 461 }
537 if (g_append_debug_token_to_trial_string) {
538 output->append("DebugToken");
539 output->append(1, kPersistentStringSeparator);
540 output->append(IntToString(g_debug_token));
541 output->append(1, kPersistentStringSeparator);
542 }
543 } 462 }
544 463
545 // static 464 // static
546 void FieldTrialList::AllStatesToString(std::string* output) { 465 void FieldTrialList::AllStatesToString(std::string* output) {
547 if (!global_) 466 if (!global_)
548 return; 467 return;
549 AutoLock auto_lock(global_->lock_); 468 AutoLock auto_lock(global_->lock_);
550 469
551 for (const auto& registered : global_->registered_) { 470 for (const auto& registered : global_->registered_) {
552 FieldTrial::State trial; 471 FieldTrial::State trial;
553 if (!registered.second->GetState(&trial)) 472 if (!registered.second->GetState(&trial))
554 continue; 473 continue;
555 DCHECK_EQ(std::string::npos, 474 DCHECK_EQ(std::string::npos,
556 trial.trial_name.find(kPersistentStringSeparator)); 475 trial.trial_name.find(kPersistentStringSeparator));
557 DCHECK_EQ(std::string::npos, 476 DCHECK_EQ(std::string::npos,
558 trial.group_name.find(kPersistentStringSeparator)); 477 trial.group_name.find(kPersistentStringSeparator));
559 if (trial.activated) 478 if (trial.activated)
560 output->append(1, kActivationMarker); 479 output->append(1, kActivationMarker);
561 trial.trial_name.AppendToString(output); 480 trial.trial_name.AppendToString(output);
562 output->append(1, kPersistentStringSeparator); 481 output->append(1, kPersistentStringSeparator);
563 trial.group_name.AppendToString(output); 482 trial.group_name.AppendToString(output);
564 output->append(1, kPersistentStringSeparator); 483 output->append(1, kPersistentStringSeparator);
565
566 // TODO(asvitkine): Remove these when http://crbug.com/359406 is fixed.
567 CheckTrialGroup(trial.trial_name.as_string(), trial.group_name.as_string(),
568 &global_->seen_states_);
569 if (g_use_global_check_states) {
570 CheckTrialGroup(trial.trial_name.as_string(),
571 trial.group_name.as_string(), &g_seen_states.Get());
572 }
573 } 484 }
574 } 485 }
575 486
576 // static 487 // static
577 void FieldTrialList::GetActiveFieldTrialGroups( 488 void FieldTrialList::GetActiveFieldTrialGroups(
578 FieldTrial::ActiveGroups* active_groups) { 489 FieldTrial::ActiveGroups* active_groups) {
579 DCHECK(active_groups->empty()); 490 DCHECK(active_groups->empty());
580 if (!global_) 491 if (!global_)
581 return; 492 return;
582 AutoLock auto_lock(global_->lock_); 493 AutoLock auto_lock(global_->lock_);
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
687 { 598 {
688 AutoLock auto_lock(global_->lock_); 599 AutoLock auto_lock(global_->lock_);
689 if (field_trial->group_reported_) 600 if (field_trial->group_reported_)
690 return; 601 return;
691 field_trial->group_reported_ = true; 602 field_trial->group_reported_ = true;
692 } 603 }
693 604
694 if (!field_trial->enable_field_trial_) 605 if (!field_trial->enable_field_trial_)
695 return; 606 return;
696 607
697 // TODO(asvitkine): Remove this block when http://crbug.com/359406 is fixed.
698 {
699 AutoLock auto_lock(global_->lock_);
700 CheckTrialGroup(field_trial->trial_name(),
701 field_trial->group_name_internal(), &global_->seen_states_);
702 if (g_use_global_check_states) {
703 CheckTrialGroup(field_trial->trial_name(),
704 field_trial->group_name_internal(), &g_seen_states.Get());
705 }
706 }
707 global_->observer_list_->Notify( 608 global_->observer_list_->Notify(
708 FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized, 609 FROM_HERE, &FieldTrialList::Observer::OnFieldTrialGroupFinalized,
709 field_trial->trial_name(), field_trial->group_name_internal()); 610 field_trial->trial_name(), field_trial->group_name_internal());
710 } 611 }
711 612
712 // static 613 // static
713 size_t FieldTrialList::GetFieldTrialCount() { 614 size_t FieldTrialList::GetFieldTrialCount() {
714 if (!global_) 615 if (!global_)
715 return 0; 616 return 0;
716 AutoLock auto_lock(global_->lock_); 617 AutoLock auto_lock(global_->lock_);
(...skipping 25 matching lines...) Expand all
742 return; 643 return;
743 } 644 }
744 AutoLock auto_lock(global_->lock_); 645 AutoLock auto_lock(global_->lock_);
745 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); 646 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name();
746 trial->AddRef(); 647 trial->AddRef();
747 trial->SetTrialRegistered(); 648 trial->SetTrialRegistered();
748 global_->registered_[trial->trial_name()] = trial; 649 global_->registered_[trial->trial_name()] = trial;
749 } 650 }
750 651
751 } // namespace base 652 } // namespace base
OLDNEW
« no previous file with comments | « base/metrics/field_trial.h ('k') | chrome/browser/chrome_browser_main.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698