Index: base/metrics/field_trial.cc |
=================================================================== |
--- base/metrics/field_trial.cc (revision 118842) |
+++ base/metrics/field_trial.cc (working copy) |
@@ -21,6 +21,9 @@ |
const int FieldTrial::kDefaultGroupNumber = 0; |
// static |
+const uint32 FieldTrial::kReservedHashValue = 0; |
+ |
+// static |
bool FieldTrial::enable_benchmarking_ = false; |
// static |
@@ -42,12 +45,14 @@ |
const int month, |
const int day_of_month) |
: name_(name), |
+ name_hash_(HashName(name)), |
divisor_(total_probability), |
default_group_name_(default_group_name), |
random_(static_cast<Probability>(divisor_ * RandDouble())), |
accumulated_group_probability_(0), |
next_group_number_(kDefaultGroupNumber + 1), |
group_(kNotFinalized), |
+ group_name_hash_(kReservedHashValue), |
enable_field_trial_(true) { |
DCHECK_GT(total_probability, 0); |
DCHECK(!name_.empty()); |
@@ -96,6 +101,7 @@ |
if (group_ != kNotFinalized) { |
group_ = kDefaultGroupNumber; |
group_name_ = default_group_name_; |
+ group_name_hash_ = HashName(group_name_); |
} |
} |
@@ -117,6 +123,7 @@ |
StringAppendF(&group_name_, "%d", group_); |
else |
group_name_ = name; |
+ group_name_hash_ = HashName(group_name_); |
FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_); |
} |
return next_group_number_++; |
@@ -127,6 +134,7 @@ |
accumulated_group_probability_ = divisor_; |
group_ = kDefaultGroupNumber; |
group_name_ = default_group_name_; |
+ group_name_hash_ = HashName(group_name_); |
FieldTrialList::NotifyFieldTrialGroupSelection(name_, group_name_); |
} |
return group_; |
@@ -138,6 +146,14 @@ |
return group_name_; |
} |
+bool FieldTrial::GetNameGroupId(NameGroupId* name_group_id) { |
+ if (group_name_hash_ == kReservedHashValue) |
+ return false; |
+ name_group_id->name = name_hash_; |
+ name_group_id->group = group_name_hash_; |
+ return true; |
+} |
+ |
// static |
std::string FieldTrial::MakeName(const std::string& name_prefix, |
const std::string& trial_name) { |
@@ -173,6 +189,21 @@ |
return BitsToOpenEndedUnitInterval(*bits); |
} |
+// static |
+uint32 FieldTrial::HashName(const std::string& name) { |
+ // SHA-1 is designed to produce a uniformly random spread in its output space, |
+ // even for nearly-identical name. |
Alexei Svitkine (slow)
2012/01/25 17:40:16
"nearly-identical name" -> "nearly-identical input
MAD
2012/01/25 18:48:53
Done.
|
+ unsigned char sha1_hash[kSHA1Length]; |
+ SHA1HashBytes(reinterpret_cast<const unsigned char*>(name.c_str()), |
Alexei Svitkine (slow)
2012/01/25 15:25:19
I think you can use |SHA1HashString()| instead of
MAD
2012/01/25 17:02:33
I copied the behavior from HashClientId... Should
Alexei Svitkine (slow)
2012/01/25 17:40:16
Looking closer at |SHA1HashString()|, it returns i
MAD
2012/01/25 18:48:53
OK, Thanks for checking... ;-)
|
+ name.size(), |
+ sha1_hash); |
+ |
+ COMPILE_ASSERT(sizeof(uint32) < sizeof(sha1_hash), need_more_data); |
+ uint32* bits = reinterpret_cast<uint32*>(&sha1_hash[0]); |
+ DCHECK(*bits != kReservedHashValue) << "Bad luck, that name can't be used!"; |
+ return *bits; |
+} |
+ |
//------------------------------------------------------------------------------ |
// FieldTrialList methods and members. |
@@ -272,6 +303,22 @@ |
} |
// static |
+void FieldTrialList::GetFieldTrialNameGroupIds( |
+ std::vector<FieldTrial::NameGroupId>* name_group_ids) { |
+ if (!global_) |
Alexei Svitkine (slow)
2012/01/25 15:25:19
Should you clear |name_group_ids| in this case (an
MAD
2012/01/25 17:02:33
Again, I copied the behavior from StatesToString w
Alexei Svitkine (slow)
2012/01/25 17:40:16
I'm okay with the DCHECK(), though then it should
MAD
2012/01/25 18:48:53
Done.
|
+ return; |
+ DCHECK(name_group_ids->empty()); |
+ AutoLock auto_lock(global_->lock_); |
+ |
+ for (RegistrationList::iterator it = global_->registered_.begin(); |
+ it != global_->registered_.end(); ++it) { |
+ FieldTrial::NameGroupId name_group_id; |
+ if (it->second->GetNameGroupId(&name_group_id)) |
+ name_group_ids->push_back(name_group_id); |
+ } |
+} |
+ |
+// static |
bool FieldTrialList::CreateTrialsInChildProcess( |
const std::string& parent_trials) { |
DCHECK(global_); |