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

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

Issue 10830318: Use a different algorithm with the low entropy source for field trials. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 8 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | base/metrics/field_trial.cc » ('j') | chrome/browser/metrics/metrics_service.h » ('J')
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 // 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 #include "base/time.h" 87 #include "base/time.h"
88 88
89 namespace base { 89 namespace base {
90 90
91 class FieldTrialList; 91 class FieldTrialList;
92 92
93 class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> { 93 class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
94 public: 94 public:
95 typedef int Probability; // Probability type for being selected in a trial. 95 typedef int Probability; // Probability type for being selected in a trial.
96 96
97 // EntropyProvider is an interface for providing entropy for one-time
98 // randomized (persistent) field trials.
99 class BASE_EXPORT EntropyProvider {
100 public:
101 virtual ~EntropyProvider() {}
Ilya Sherman 2012/08/17 07:34:28 nit: Virtual functions should never be inlined.
Alexei Svitkine (slow) 2012/08/17 14:08:59 Done. I also fixed this for FieldTrialList::Observ
102
103 // Returns a double in the range of [0, 1) based on |trial_name| that will
104 // be used for the dice roll for the specified field trial. A given instance
105 // should always return the same value given the same input |trial_name|.
106 virtual double GetEntropyForTrial(const std::string& trial_name) = 0;
107 };
108
97 // A pair representing a Field Trial and its selected group. 109 // A pair representing a Field Trial and its selected group.
98 struct SelectedGroup { 110 struct SelectedGroup {
99 std::string trial; 111 std::string trial;
100 std::string group; 112 std::string group;
101 }; 113 };
102 114
103 typedef std::vector<SelectedGroup> SelectedGroups; 115 typedef std::vector<SelectedGroup> SelectedGroups;
104 116
105 // A return value to indicate that a given instance has not yet had a group 117 // A return value to indicate that a given instance has not yet had a group
106 // assignment (and hence is not yet participating in the trial). 118 // assignment (and hence is not yet participating in the trial).
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 193
182 friend class base::FieldTrialList; 194 friend class base::FieldTrialList;
183 195
184 friend class RefCounted<FieldTrial>; 196 friend class RefCounted<FieldTrial>;
185 197
186 // This is the group number of the 'default' group when a choice wasn't forced 198 // This is the group number of the 'default' group when a choice wasn't forced
187 // by a call to FieldTrialList::CreateFieldTrial. It is kept private so that 199 // by a call to FieldTrialList::CreateFieldTrial. It is kept private so that
188 // consumers don't use it by mistake in cases where the group was forced. 200 // consumers don't use it by mistake in cases where the group was forced.
189 static const int kDefaultGroupNumber; 201 static const int kDefaultGroupNumber;
190 202
191 FieldTrial(const std::string& name, 203 FieldTrial(EntropyProvider* entropy_provider,
Ilya Sherman 2012/08/17 07:34:28 nit: Unless you're planning to modify the |entropy
Alexei Svitkine (slow) 2012/08/17 14:08:59 Done.
204 const std::string& name,
192 Probability total_probability, 205 Probability total_probability,
193 const std::string& default_group_name); 206 const std::string& default_group_name);
194 virtual ~FieldTrial(); 207 virtual ~FieldTrial();
195 208
196 // Return the default group name of the FieldTrial. 209 // Return the default group name of the FieldTrial.
197 std::string default_group_name() const { return default_group_name_; } 210 std::string default_group_name() const { return default_group_name_; }
198 211
199 // Sets the group_name as well as group_name_hash to make sure they are sync. 212 // Sets the group_name as well as group_name_hash to make sure they are sync.
200 void SetGroupChoice(const std::string& name, int number); 213 void SetGroupChoice(const std::string& name, int number);
201 214
202 // Returns the group_name. A winner need not have been chosen. 215 // Returns the group_name. A winner need not have been chosen.
203 std::string group_name_internal() const { return group_name_; } 216 std::string group_name_internal() const { return group_name_; }
204 217
205 // Calculates a uniformly-distributed double between [0.0, 1.0) given 218 // Entropy provider that will be used if the field trial uses one-time
206 // a |client_id| and a |trial_name| (the latter is used as salt to avoid 219 // randomization. Weak pointer, owned by FieldTrialList.
207 // separate one-time randomized trials from all having the same results). 220 EntropyProvider* entropy_provider_;
Ilya Sherman 2012/08/17 07:34:28 nit: const EntropyProvider* const?
Alexei Svitkine (slow) 2012/08/17 14:08:59 Done.
208 static double HashClientId(const std::string& client_id,
209 const std::string& trial_name);
210 221
211 // The name of the field trial, as can be found via the FieldTrialList. 222 // The name of the field trial, as can be found via the FieldTrialList.
212 const std::string name_; 223 const std::string name_;
213 224
214 // The maximum sum of all probabilities supplied, which corresponds to 100%. 225 // The maximum sum of all probabilities supplied, which corresponds to 100%.
215 // This is the scaling factor used to adjust supplied probabilities. 226 // This is the scaling factor used to adjust supplied probabilities.
216 const Probability divisor_; 227 const Probability divisor_;
217 228
218 // The name of the default group. 229 // The name of the default group.
219 const std::string default_group_name_; 230 const std::string default_group_name_;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
271 // Notify observers when FieldTrials's group is selected. 282 // Notify observers when FieldTrials's group is selected.
272 virtual void OnFieldTrialGroupFinalized(const std::string& trial_name, 283 virtual void OnFieldTrialGroupFinalized(const std::string& trial_name,
273 const std::string& group_name) = 0; 284 const std::string& group_name) = 0;
274 285
275 protected: 286 protected:
276 virtual ~Observer() {} 287 virtual ~Observer() {}
277 }; 288 };
278 289
279 // This singleton holds the global list of registered FieldTrials. 290 // This singleton holds the global list of registered FieldTrials.
280 // 291 //
281 // |client_id| should be an opaque, diverse ID for this client that does not 292 // To support one-time randomized field trials, specify a non-NULL
282 // change between sessions, to enable one-time randomized trials. The empty 293 // |entropy_provider| which should be a source of uniformly distributed
283 // string may be provided, in which case one-time randomized trials will 294 // entropy values.
284 // not be available. 295 explicit FieldTrialList(FieldTrial::EntropyProvider* entropy_provider);
285 explicit FieldTrialList(const std::string& client_id); 296
286 // Destructor Release()'s references to all registered FieldTrial instances. 297 // Destructor Release()'s references to all registered FieldTrial instances.
287 ~FieldTrialList(); 298 ~FieldTrialList();
288 299
289 // Get a FieldTrial instance from the factory. 300 // Get a FieldTrial instance from the factory.
290 // 301 //
291 // |name| is used to register the instance with the FieldTrialList class, 302 // |name| is used to register the instance with the FieldTrialList class,
292 // and can be used to find the trial (only one trial can be present for each 303 // and can be used to find the trial (only one trial can be present for each
293 // name). |default_group_name| is the name of the default group which will 304 // name). |default_group_name| is the name of the default group which will
294 // be chosen if none of the subsequent appended groups get to be chosen. 305 // be chosen if none of the subsequent appended groups get to be chosen.
295 // |default_group_number| can receive the group number of the default group as 306 // |default_group_number| can receive the group number of the default group as
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
386 } 397 }
387 398
388 // Return the number of active field trials. 399 // Return the number of active field trials.
389 static size_t GetFieldTrialCount(); 400 static size_t GetFieldTrialCount();
390 401
391 // Returns true if you can call |FieldTrial::UseOneTimeRandomization()| 402 // Returns true if you can call |FieldTrial::UseOneTimeRandomization()|
392 // without error, i.e. if a non-empty string was provided as the client_id 403 // without error, i.e. if a non-empty string was provided as the client_id
393 // when constructing the FieldTrialList singleton. 404 // when constructing the FieldTrialList singleton.
394 static bool IsOneTimeRandomizationEnabled(); 405 static bool IsOneTimeRandomizationEnabled();
395 406
396 // Returns an opaque, diverse ID for this client that does not change
397 // between sessions.
398 //
399 // Returns the empty string if one-time randomization is not enabled.
400 static const std::string& client_id();
401
402 private: 407 private:
403 // A map from FieldTrial names to the actual instances. 408 // A map from FieldTrial names to the actual instances.
404 typedef std::map<std::string, FieldTrial*> RegistrationList; 409 typedef std::map<std::string, FieldTrial*> RegistrationList;
405 410
406 // Helper function should be called only while holding lock_. 411 // Helper function should be called only while holding lock_.
407 FieldTrial* PreLockedFind(const std::string& name); 412 FieldTrial* PreLockedFind(const std::string& name);
408 413
409 // Register() stores a pointer to the given trial in a global map. 414 // Register() stores a pointer to the given trial in a global map.
410 // This method also AddRef's the indicated trial. 415 // This method also AddRef's the indicated trial.
411 // This should always be called after creating a new FieldTrial instance. 416 // This should always be called after creating a new FieldTrial instance.
412 static void Register(FieldTrial* trial); 417 static void Register(FieldTrial* trial);
413 418
414 static FieldTrialList* global_; // The singleton of this class. 419 static FieldTrialList* global_; // The singleton of this class.
415 420
416 // This will tell us if there is an attempt to register a field 421 // This will tell us if there is an attempt to register a field
417 // trial or check if one-time randomization is enabled without 422 // trial or check if one-time randomization is enabled without
418 // creating the FieldTrialList. This is not an error, unless a 423 // creating the FieldTrialList. This is not an error, unless a
419 // FieldTrialList is created after that. 424 // FieldTrialList is created after that.
420 static bool used_without_global_; 425 static bool used_without_global_;
421 426
422 // A helper value made available to users, that shows when the FieldTrialList 427 // A helper value made available to users, that shows when the FieldTrialList
423 // was initialized. Note that this is a singleton instance, and hence is a 428 // was initialized. Note that this is a singleton instance, and hence is a
424 // good approximation to the start of the process. 429 // good approximation to the start of the process.
425 TimeTicks application_start_time_; 430 TimeTicks application_start_time_;
426 431
427 // Lock for access to registered_. 432 // Lock for access to registered_.
428 base::Lock lock_; 433 base::Lock lock_;
429 RegistrationList registered_; 434 RegistrationList registered_;
430 435
431 // An opaque, diverse ID for this client that does not change 436 // Entropy provider to be used for one-time randomized field trials. If NULL,
432 // between sessions, or the empty string if not initialized. 437 // one-time randomization is not supported.
433 std::string client_id_; 438 scoped_ptr<FieldTrial::EntropyProvider> entropy_provider_;
434 439
435 // List of observers to be notified when a group is selected for a FieldTrial. 440 // List of observers to be notified when a group is selected for a FieldTrial.
436 scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_; 441 scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_;
437 442
438 DISALLOW_COPY_AND_ASSIGN(FieldTrialList); 443 DISALLOW_COPY_AND_ASSIGN(FieldTrialList);
439 }; 444 };
440 445
441 } // namespace base 446 } // namespace base
442 447
443 #endif // BASE_METRICS_FIELD_TRIAL_H_ 448 #endif // BASE_METRICS_FIELD_TRIAL_H_
OLDNEW
« no previous file with comments | « no previous file | base/metrics/field_trial.cc » ('j') | chrome/browser/metrics/metrics_service.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698