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

Unified Diff: base/field_trial.h

Issue 28226: Renovate FieldTrial class to better fit with histogram usage. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | base/field_trial.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: base/field_trial.h
===================================================================
--- base/field_trial.h (revision 10679)
+++ base/field_trial.h (working copy)
@@ -6,16 +6,65 @@
// performed by actual users in the field (i.e., in a shipped or beta product).
// All code is called exclusively on the UI thread currently.
//
-// The simplest example is a test to see whether one of two options produces
-// "better" results across our user population. In that scenario, UMA data
-// is uploaded to show the test results, and this class manages the state of
-// each such test (state == which option was pseudo-randomly selected).
+// The simplest example is an experiment to see whether one of two options
+// produces "better" results across our user population. In that scenario, UMA
+// data is uploaded to aggregate the test results, and this FieldTrial class
+// manages the state of each such experiment (state == which option was
+// pseudo-randomly selected).
+//
// States are typically generated randomly, either based on a one time
-// randomization (reused during each run of the program), or by a startup
-// randomization (keeping that tests state constant across a run), or by
-// continuous randomization across a run.
-// Only startup randomization is implemented (thus far).
+// randomization (generated randomly once, and then persitently reused in the
+// client during each future run of the program), or by a startup randomization
+// (generated each time the application starts up, but held constant during the
+// duration of the process), or by continuous randomization across a run (where
+// the state can be recalculated again and again, many times during a process).
+// Only startup randomization is implemented thus far.
+//------------------------------------------------------------------------------
+// Example: Suppose we have an experiment involving memory, such as determining
+// the impact of memory model command line flags actual memory use.
+// We assume that we already have a histogram of memory usage, such as:
+
+// HISTOGRAM_COUNTS("Memory.RendererTotal", count);
+
+// Somewhere in main thread initialization code, we'd probably define an
+// instance of a FieldTrial, with code such as:
+
+// // Note, FieldTrials are reference counted, and persist automagically until
+// // process teardown, courtesy of their automatic registration in
+// // FieldTrialList.
+// trial = new FieldTrial("MemoryExperiment", 1000);
+// group1 = trial->AppendGroup("_high_mem", 20); // 2% this _high_mem group.
+// group2 = trial->AppendGroup("_low_mem", 20); // 2% this _low_mem group.
+// // Take action depending of which group we randomly land in.
+// switch (trial->group()) {
+// case group1:
+// ... do something
+// break;
+// case group2:
+// ....
+// break;
+// default:
+// ...
+// }
+
+// We then modify any histograms we wish to correlate with our experiment to
+// have slighly different names, depending on what group the trial instance
+// happened (randomly) to be assigned to:
+
+// HISTOGRAM_COUNTS(FieldTrial::MakeName("Memory.RendererTotal",
+// "MemoryExperiment"), count);
+
+// The above code will create 3 distinct histograms, with each run of the
+// application being assigned to of of teh three groups, and for each group, the
+// correspondingly named histogram will be populated:
+
+// Memory.RendererTotal // 96% of users still fill this histogram.
+// Memory.RendererTotal_high_mem // 2% of users will fill this histogram.
+// Memory.RendererTotal_low_mem // 2% of users will fill this histogram.
+
+//------------------------------------------------------------------------------
+
#ifndef BASE_FIELD_TRIAL_H_
#define BASE_FIELD_TRIAL_H_
@@ -26,27 +75,74 @@
#include "base/ref_counted.h"
#include "base/time.h"
+
class FieldTrial : public base::RefCounted<FieldTrial> {
public:
- // Constructor for a 2-state (boolean) trial.
+ static const int kNotParticipating = -1;
+
+ typedef int Probability; // Use scaled up probability.
+
// The name is used to register the instance with the FieldTrialList class,
// and can be used to find the trial (only one trial can be present for each
- // name) using the Find() method.
- // The probability is a number in the range [0, 1], and is the likliehood that
- // the assigned boolean value will be true.
- FieldTrial(const std::wstring& name, double probability);
+ // name).
+ // Group probabilities that are later supplied must sum to less than or equal
+ // to the total_probability.
+ FieldTrial(const std::string& name, Probability total_probability);
- // Return the selected boolean value.
- bool boolean_value() const { return boolean_value_; }
- std::wstring name() const { return name_; }
+ // Establish the name and probability of the next group in this trial.
+ // Sometimes, based on construction randomization, this call may causes the
+ // provided group to be *THE* group selected for use in this instance.
+ int AppendGroup(const std::string& name, Probability group_probability);
+ // Return the name of the FieldTrial (excluding the group name).
+ std::string name() const { return name_; }
+
+ // Return the randomly selected group number that was assigned.
+ // Return kNotParticipating if the instance is not participating in the
+ // experiment.
+ int group() const { return group_; }
+
+ // If the field trial is not in an experiment, this returns the empty string.
+ // if the group's name is empty, a name of "_" concatenated with the group
+ // number is used as the group name.
+ std::string group_name() const { return group_name_; }
+
+ // Helper function for the most common use: as an argument to specifiy the
+ // name of a HISTOGRAM. Use the original histogram name as the name_prefix.
+ static std::string MakeName(const std::string& name_prefix,
+ const std::string& trial_name);
+
private:
- const std::wstring name_;
- bool boolean_value_;
+ // The name of the field trial, as can be found via the FieldTrialList.
+ // This is empty of the trial is not in the experiment.
+ const std::string name_;
+ // The maximu sum of all probabilities supplied, which corresponds to 100%.
+ // This is the scaling factor used to adjust supplied probabilities.
+ Probability divisor_;
+
+ // The randomly selected probability that is used to select a group (or have
+ // the instance not participate). It is the product of divisor_ and a random
+ // number between [0, 1).
+ Probability random_;
+
+ // Sum of the probabilities of all appended groups.
+ Probability accumulated_group_probability_;
+
+ int next_group_number_;
+
+ // The pseudo-randomly assigned group number.
+ // This is kNotParticipating if no group has been assigned.
+ int group_;
+
+ // A textual name for the randomly selected group, including the Trial name.
+ // If this Trial is not a member of an group, this string is empty.
+ std::string group_name_;
+
DISALLOW_COPY_AND_ASSIGN(FieldTrial);
};
+//------------------------------------------------------------------------------
// Class with a list of all active field trials. A trial is active if it has
// been registered, which includes evaluating its state based on its probaility.
// Only one instance of this class exists.
@@ -63,12 +159,16 @@
// The Find() method can be used to test to see if a named Trial was already
// registered, or to retrieve a pointer to it from the global map.
- static FieldTrial* Find(const std::wstring& name);
+ static FieldTrial* Find(const std::string& name);
+ static int FindValue(const std::string& name);
+
+ static std::string FindFullName(const std::string& name);
+
// The time of construction of the global map is recorded in a static variable
// and is commonly used by experiments to identify the time since the start
// of the application. In some experiments it may be useful to discount
- // data that is gathered before the application has reach sufficient
+ // data that is gathered before the application has reached sufficient
// stability (example: most DLL have loaded, etc.)
static base::Time application_start_time() {
if (global_)
@@ -78,7 +178,7 @@
}
private:
- typedef std::map<std::wstring, FieldTrial*> RegistrationList;
+ typedef std::map<std::string, FieldTrial*> RegistrationList;
static FieldTrialList* global_; // The singleton of this class.
« no previous file with comments | « no previous file | base/field_trial.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698