summaryrefslogtreecommitdiffstats
path: root/base/metrics/field_trial.cc
diff options
context:
space:
mode:
Diffstat (limited to 'base/metrics/field_trial.cc')
-rw-r--r--base/metrics/field_trial.cc119
1 files changed, 89 insertions, 30 deletions
diff --git a/base/metrics/field_trial.cc b/base/metrics/field_trial.cc
index 654746c..5db88c1 100644
--- a/base/metrics/field_trial.cc
+++ b/base/metrics/field_trial.cc
@@ -7,14 +7,15 @@
#include "base/logging.h"
#include "base/rand_util.h"
#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
namespace base {
// static
-const int FieldTrial::kNotParticipating = -1;
+const int FieldTrial::kNotFinalized = -1;
// static
-const int FieldTrial::kAllRemainingProbability = -2;
+const int FieldTrial::kDefaultGroupNumber = 0;
// static
bool FieldTrial::enable_benchmarking_ = false;
@@ -28,30 +29,53 @@ static const char kHistogramFieldTrialSeparator('_');
// FieldTrial methods and members.
FieldTrial::FieldTrial(const std::string& name,
- const Probability total_probability)
+ const Probability total_probability,
+ const std::string& default_group_name,
+ const int year,
+ const int month,
+ const int day_of_month)
: name_(name),
divisor_(total_probability),
+ default_group_name_(default_group_name),
random_(static_cast<Probability>(divisor_ * base::RandDouble())),
accumulated_group_probability_(0),
- next_group_number_(0),
- group_(kNotParticipating) {
+ next_group_number_(kDefaultGroupNumber+1),
+ group_(kNotFinalized) {
+ DCHECK(!default_group_name_.empty());
FieldTrialList::Register(this);
+
+ DCHECK_GT(year, 1970);
+ DCHECK_GT(month, 0);
+ DCHECK_LT(month, 13);
+ DCHECK_GT(day_of_month, 0);
+ DCHECK_LT(day_of_month, 32);
+
+ base::Time::Exploded exploded;
+ exploded.year = year;
+ exploded.month = month;
+ exploded.day_of_week = 0; // Should be unusued.
+ exploded.day_of_month = day_of_month;
+ exploded.hour = 0;
+ exploded.minute = 0;
+ exploded.second = 0;
+ exploded.millisecond = 0;
+
+ base::Time expiration_time = Time::FromLocalExploded(exploded);
+ disable_field_trial_ = (GetBuildTime() > expiration_time) ? true : false;
}
int FieldTrial::AppendGroup(const std::string& name,
Probability group_probability) {
DCHECK(group_probability <= divisor_);
- DCHECK(group_probability >=0 ||
- group_probability == kAllRemainingProbability);
- if (group_probability == kAllRemainingProbability) {
- accumulated_group_probability_ = divisor_;
- } else {
- if (enable_benchmarking_)
- group_probability = 0;
- accumulated_group_probability_ += group_probability;
- }
+ DCHECK_GE(group_probability, 0);
+
+ if (enable_benchmarking_ || disable_field_trial_)
+ group_probability = 0;
+
+ accumulated_group_probability_ += group_probability;
+
DCHECK(accumulated_group_probability_ <= divisor_);
- if (group_ == kNotParticipating && accumulated_group_probability_ > random_) {
+ if (group_ == kNotFinalized && accumulated_group_probability_ > random_) {
// This is the group that crossed the random line, so we do the assignment.
group_ = next_group_number_;
if (name.empty())
@@ -62,6 +86,20 @@ int FieldTrial::AppendGroup(const std::string& name,
return next_group_number_++;
}
+int FieldTrial::group() {
+ if (group_ == kNotFinalized) {
+ accumulated_group_probability_ = divisor_;
+ group_ = kDefaultGroupNumber;
+ group_name_ = default_group_name_;
+ }
+ return group_;
+}
+
+std::string FieldTrial::group_name() {
+ group(); // call group() to make group assignment was done.
+ return group_name_;
+}
+
// static
std::string FieldTrial::MakeName(const std::string& name_prefix,
const std::string& trial_name) {
@@ -76,6 +114,16 @@ void FieldTrial::EnableBenchmarking() {
enable_benchmarking_ = true;
}
+// static
+Time FieldTrial::GetBuildTime() {
+ Time integral_build_time;
+ const char* kDateTime = __DATE__ " " __TIME__;
+ bool result = Time::FromString(ASCIIToWide(kDateTime).c_str(),
+ &integral_build_time);
+ DCHECK(result);
+ return integral_build_time;
+}
+
FieldTrial::~FieldTrial() {}
//------------------------------------------------------------------------------
@@ -129,7 +177,7 @@ int FieldTrialList::FindValue(const std::string& name) {
FieldTrial* field_trial = Find(name);
if (field_trial)
return field_trial->group();
- return FieldTrial::kNotParticipating;
+ return FieldTrial::kNotFinalized;
}
// static
@@ -149,9 +197,11 @@ void FieldTrialList::StatesToString(std::string* output) {
for (RegistrationList::iterator it = global_->registered_.begin();
it != global_->registered_.end(); ++it) {
const std::string name = it->first;
- const std::string group_name = it->second->group_name();
+ std::string group_name = it->second->group_name_internal();
if (group_name.empty())
- continue; // No definitive winner in this trial.
+ // No definitive winner in this trial, use default_group_name as the
+ // group_name.
+ group_name = it->second->default_group_name();
DCHECK_EQ(name.find(kPersistentStringSeparator), std::string::npos);
DCHECK_EQ(group_name.find(kPersistentStringSeparator), std::string::npos);
output->append(name);
@@ -162,34 +212,43 @@ void FieldTrialList::StatesToString(std::string* output) {
}
// static
-bool FieldTrialList::StringAugmentsState(const std::string& prior_state) {
+bool FieldTrialList::CreateTrialsInChildProcess(
+ const std::string& parent_trials) {
DCHECK(global_);
- if (prior_state.empty() || !global_)
+ if (parent_trials.empty() || !global_)
return true;
+ Time::Exploded exploded;
+ Time two_years_from_now =
+ Time::NowFromSystemTime() + TimeDelta::FromDays(730);
+ two_years_from_now.LocalExplode(&exploded);
+ const int kTwoYearsFromNow = exploded.year;
+
size_t next_item = 0;
- while (next_item < prior_state.length()) {
- size_t name_end = prior_state.find(kPersistentStringSeparator, next_item);
- if (name_end == prior_state.npos || next_item == name_end)
+ while (next_item < parent_trials.length()) {
+ size_t name_end = parent_trials.find(kPersistentStringSeparator, next_item);
+ if (name_end == parent_trials.npos || next_item == name_end)
return false;
- size_t group_name_end = prior_state.find(kPersistentStringSeparator,
- name_end + 1);
- if (group_name_end == prior_state.npos || name_end + 1 == group_name_end)
+ size_t group_name_end = parent_trials.find(kPersistentStringSeparator,
+ name_end + 1);
+ if (group_name_end == parent_trials.npos || name_end + 1 == group_name_end)
return false;
- std::string name(prior_state, next_item, name_end - next_item);
- std::string group_name(prior_state, name_end + 1,
+ std::string name(parent_trials, next_item, name_end - next_item);
+ std::string group_name(parent_trials, name_end + 1,
group_name_end - name_end - 1);
next_item = group_name_end + 1;
FieldTrial *field_trial(FieldTrialList::Find(name));
if (field_trial) {
// In single process mode, we may have already created the field trial.
- if (field_trial->group_name() != group_name)
+ if ((field_trial->group_name_internal() != group_name) &&
+ (field_trial->default_group_name() != group_name))
return false;
continue;
}
const int kTotalProbability = 100;
- field_trial = new FieldTrial(name, kTotalProbability);
+ field_trial = new FieldTrial(name, kTotalProbability, group_name,
+ kTwoYearsFromNow, 1, 1);
field_trial->AppendGroup(group_name, kTotalProbability);
}
return true;