| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 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 // FieldTrial is a class for handling details of statistical experiments | 5 // FieldTrial is a class for handling details of statistical experiments |
| 6 // performed by actual users in the field (i.e., in a shipped or beta product). | 6 // performed by actual users in the field (i.e., in a shipped or beta product). |
| 7 // All code is called exclusively on the UI thread currently. | 7 // All code is called exclusively on the UI thread currently. |
| 8 // | 8 // |
| 9 // The simplest example is an experiment to see whether one of two options | 9 // The simplest example is an experiment to see whether one of two options |
| 10 // produces "better" results across our user population. In that scenario, UMA | 10 // produces "better" results across our user population. In that scenario, UMA |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 #include <map> | 65 #include <map> |
| 66 #include <string> | 66 #include <string> |
| 67 | 67 |
| 68 #include "base/lock.h" | 68 #include "base/lock.h" |
| 69 #include "base/ref_counted.h" | 69 #include "base/ref_counted.h" |
| 70 #include "base/time.h" | 70 #include "base/time.h" |
| 71 | 71 |
| 72 | 72 |
| 73 class FieldTrial : public base::RefCounted<FieldTrial> { | 73 class FieldTrial : public base::RefCounted<FieldTrial> { |
| 74 public: | 74 public: |
| 75 typedef int Probability; // Probability type for being selected in a trial. |
| 76 |
| 77 // A return value to indicate that a given instance has not yet had a group |
| 78 // assignment (and hence is not yet participating in the trial). |
| 75 static const int kNotParticipating; | 79 static const int kNotParticipating; |
| 76 | 80 |
| 77 // Define a separator charactor to use when creating a persistent form of an | 81 // Provide an easy way to assign all remaining probability to a group. Note |
| 78 // instance. This is intended for use as a command line argument, passed to a | 82 // that this will force an instance to participate, and make it illegal to |
| 79 // second process to mimic our state (i.e., provide the same group name). | 83 // attempt to probabalistically add any other groups to the trial. |
| 80 static const char kPersistentStringSeparator; // Currently a slash. | 84 static const Probability kAllRemainingProbability; |
| 81 | |
| 82 typedef int Probability; // Use scaled up probability. | |
| 83 | 85 |
| 84 // The name is used to register the instance with the FieldTrialList class, | 86 // The name is used to register the instance with the FieldTrialList class, |
| 85 // and can be used to find the trial (only one trial can be present for each | 87 // and can be used to find the trial (only one trial can be present for each |
| 86 // name). | 88 // name). |
| 87 // Group probabilities that are later supplied must sum to less than or equal | 89 // Group probabilities that are later supplied must sum to less than or equal |
| 88 // to the total_probability. | 90 // to the total_probability. |
| 89 FieldTrial(const std::string& name, Probability total_probability); | 91 FieldTrial(const std::string& name, Probability total_probability); |
| 90 | 92 |
| 91 // Establish the name and probability of the next group in this trial. | 93 // Establish the name and probability of the next group in this trial. |
| 92 // Sometimes, based on construction randomization, this call may causes the | 94 // Sometimes, based on construction randomization, this call may causes the |
| (...skipping 11 matching lines...) Expand all Loading... |
| 104 // If the field trial is not in an experiment, this returns the empty string. | 106 // If the field trial is not in an experiment, this returns the empty string. |
| 105 // if the group's name is empty, a name of "_" concatenated with the group | 107 // if the group's name is empty, a name of "_" concatenated with the group |
| 106 // number is used as the group name. | 108 // number is used as the group name. |
| 107 std::string group_name() const { return group_name_; } | 109 std::string group_name() const { return group_name_; } |
| 108 | 110 |
| 109 // Helper function for the most common use: as an argument to specifiy the | 111 // Helper function for the most common use: as an argument to specifiy the |
| 110 // name of a HISTOGRAM. Use the original histogram name as the name_prefix. | 112 // name of a HISTOGRAM. Use the original histogram name as the name_prefix. |
| 111 static std::string MakeName(const std::string& name_prefix, | 113 static std::string MakeName(const std::string& name_prefix, |
| 112 const std::string& trial_name); | 114 const std::string& trial_name); |
| 113 | 115 |
| 114 // Create a persistent representation of the instance that could be resurected | |
| 115 // in another process. This allows randomization to be done in one process, | |
| 116 // and secondary processes can by synchronized on the result. | |
| 117 // The resulting string contains only the name, the trial name, and a "/" | |
| 118 // separator. | |
| 119 std::string MakePersistentString() const; | |
| 120 | |
| 121 // Using a string created by MakePersistentString(), construct a new instance | |
| 122 // that has the same state as the original instance. Currently only the | |
| 123 // group_name_ and name_ are restored. | |
| 124 static FieldTrial* RestorePersistentString(const std::string &persistent); | |
| 125 | |
| 126 private: | 116 private: |
| 127 // The name of the field trial, as can be found via the FieldTrialList. | 117 // The name of the field trial, as can be found via the FieldTrialList. |
| 128 // This is empty of the trial is not in the experiment. | 118 // This is empty of the trial is not in the experiment. |
| 129 const std::string name_; | 119 const std::string name_; |
| 130 | 120 |
| 131 // The maximu sum of all probabilities supplied, which corresponds to 100%. | 121 // The maximu sum of all probabilities supplied, which corresponds to 100%. |
| 132 // This is the scaling factor used to adjust supplied probabilities. | 122 // This is the scaling factor used to adjust supplied probabilities. |
| 133 Probability divisor_; | 123 Probability divisor_; |
| 134 | 124 |
| 135 // The randomly selected probability that is used to select a group (or have | 125 // The randomly selected probability that is used to select a group (or have |
| (...skipping 16 matching lines...) Expand all Loading... |
| 152 | 142 |
| 153 DISALLOW_COPY_AND_ASSIGN(FieldTrial); | 143 DISALLOW_COPY_AND_ASSIGN(FieldTrial); |
| 154 }; | 144 }; |
| 155 | 145 |
| 156 //------------------------------------------------------------------------------ | 146 //------------------------------------------------------------------------------ |
| 157 // Class with a list of all active field trials. A trial is active if it has | 147 // Class with a list of all active field trials. A trial is active if it has |
| 158 // been registered, which includes evaluating its state based on its probaility. | 148 // been registered, which includes evaluating its state based on its probaility. |
| 159 // Only one instance of this class exists. | 149 // Only one instance of this class exists. |
| 160 class FieldTrialList { | 150 class FieldTrialList { |
| 161 public: | 151 public: |
| 152 // Define a separator charactor to use when creating a persistent form of an |
| 153 // instance. This is intended for use as a command line argument, passed to a |
| 154 // second process to mimic our state (i.e., provide the same group name). |
| 155 static const char kPersistentStringSeparator; // Currently a slash. |
| 156 |
| 162 // This singleton holds the global list of registered FieldTrials. | 157 // This singleton holds the global list of registered FieldTrials. |
| 163 FieldTrialList(); | 158 FieldTrialList(); |
| 164 // Destructor Release()'s references to all registered FieldTrial instances. | 159 // Destructor Release()'s references to all registered FieldTrial instances. |
| 165 ~FieldTrialList(); | 160 ~FieldTrialList(); |
| 166 | 161 |
| 167 // Register() stores a pointer to the given trial in a global map. | 162 // Register() stores a pointer to the given trial in a global map. |
| 168 // This method also AddRef's the indicated trial. | 163 // This method also AddRef's the indicated trial. |
| 169 static void Register(FieldTrial* trial); | 164 static void Register(FieldTrial* trial); |
| 170 | 165 |
| 171 // The Find() method can be used to test to see if a named Trial was already | 166 // The Find() method can be used to test to see if a named Trial was already |
| 172 // registered, or to retrieve a pointer to it from the global map. | 167 // registered, or to retrieve a pointer to it from the global map. |
| 173 static FieldTrial* Find(const std::string& name); | 168 static FieldTrial* Find(const std::string& name); |
| 174 | 169 |
| 175 static int FindValue(const std::string& name); | 170 static int FindValue(const std::string& name); |
| 176 | 171 |
| 177 static std::string FindFullName(const std::string& name); | 172 static std::string FindFullName(const std::string& name); |
| 178 | 173 |
| 174 // Create a persistent representation of all FieldTrial instances for |
| 175 // resurrection in another process. This allows randomization to be done in |
| 176 // one process, and secondary processes can by synchronized on the result. |
| 177 // The resulting string contains only the names, the trial name, and a "/" |
| 178 // separator. |
| 179 static void StatesToString(std::string* output); |
| 180 |
| 181 // Use a previously generated state string (re: StatesToString()) augment the |
| 182 // current list of field tests to include the supplied tests, and using a 100% |
| 183 // probability for each test, force them to have the same group string. This |
| 184 // is commonly used in a sub-process, to carry randomly selected state in a |
| 185 // parent process into this sub-process. |
| 186 // Currently only the group_name_ and name_ are restored. |
| 187 static bool StringAugmentsState(const std::string& prior_state); |
| 188 |
| 179 // The time of construction of the global map is recorded in a static variable | 189 // The time of construction of the global map is recorded in a static variable |
| 180 // and is commonly used by experiments to identify the time since the start | 190 // and is commonly used by experiments to identify the time since the start |
| 181 // of the application. In some experiments it may be useful to discount | 191 // of the application. In some experiments it may be useful to discount |
| 182 // data that is gathered before the application has reached sufficient | 192 // data that is gathered before the application has reached sufficient |
| 183 // stability (example: most DLL have loaded, etc.) | 193 // stability (example: most DLL have loaded, etc.) |
| 184 static base::Time application_start_time() { | 194 static base::Time application_start_time() { |
| 185 if (global_) | 195 if (global_) |
| 186 return global_->application_start_time_; | 196 return global_->application_start_time_; |
| 187 // For testing purposes only, or when we don't yet have a start time. | 197 // For testing purposes only, or when we don't yet have a start time. |
| 198 // TODO(jar): Switch to TimeTicks |
| 188 return base::Time::Now(); | 199 return base::Time::Now(); |
| 189 } | 200 } |
| 190 | 201 |
| 191 private: | 202 private: |
| 192 // Helper function should be called only while holding lock_. | 203 // Helper function should be called only while holding lock_. |
| 193 FieldTrial* PreLockedFind(const std::string& name); | 204 FieldTrial* PreLockedFind(const std::string& name); |
| 194 | 205 |
| 206 // A map from FieldTrial names to the actual instances. |
| 195 typedef std::map<std::string, FieldTrial*> RegistrationList; | 207 typedef std::map<std::string, FieldTrial*> RegistrationList; |
| 196 | 208 |
| 197 static FieldTrialList* global_; // The singleton of this class. | 209 static FieldTrialList* global_; // The singleton of this class. |
| 198 | 210 |
| 211 // A helper value made availabel to users, that shows when the FieldTrialList |
| 212 // was initialized. Note that this is a singleton instance, and hence is a |
| 213 // good approximation to the start of the process. |
| 199 base::Time application_start_time_; | 214 base::Time application_start_time_; |
| 200 | 215 |
| 201 // Lock for access to registered_. | 216 // Lock for access to registered_. |
| 202 Lock lock_; | 217 Lock lock_; |
| 203 RegistrationList registered_; | 218 RegistrationList registered_; |
| 204 | 219 |
| 205 DISALLOW_COPY_AND_ASSIGN(FieldTrialList); | 220 DISALLOW_COPY_AND_ASSIGN(FieldTrialList); |
| 206 }; | 221 }; |
| 207 | 222 |
| 208 #endif // BASE_FIELD_TRIAL_H_ | 223 #endif // BASE_FIELD_TRIAL_H_ |
| 224 |
| OLD | NEW |