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

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 | « .gitignore ('k') | base/metrics/field_trial.cc » ('j') | no next file with comments »
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 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 #include "base/time.h" 88 #include "base/time.h"
89 89
90 namespace base { 90 namespace base {
91 91
92 class FieldTrialList; 92 class FieldTrialList;
93 93
94 class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> { 94 class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> {
95 public: 95 public:
96 typedef int Probability; // Probability type for being selected in a trial. 96 typedef int Probability; // Probability type for being selected in a trial.
97 97
98 // EntropyProvider is an interface for providing entropy for one-time
99 // randomized (persistent) field trials.
100 class BASE_EXPORT EntropyProvider {
101 public:
102 virtual ~EntropyProvider();
103
104 // Returns a double in the range of [0, 1) based on |trial_name| that will
105 // be used for the dice roll for the specified field trial. A given instance
106 // should always return the same value given the same input |trial_name|.
107 virtual double GetEntropyForTrial(const std::string& trial_name) const = 0;
108 };
109
98 // A pair representing a Field Trial and its selected group. 110 // A pair representing a Field Trial and its selected group.
99 struct SelectedGroup { 111 struct SelectedGroup {
100 std::string trial; 112 std::string trial;
101 std::string group; 113 std::string group;
102 }; 114 };
103 115
104 typedef std::vector<SelectedGroup> SelectedGroups; 116 typedef std::vector<SelectedGroup> SelectedGroups;
105 117
106 // A return value to indicate that a given instance has not yet had a group 118 // A return value to indicate that a given instance has not yet had a group
107 // assignment (and hence is not yet participating in the trial). 119 // assignment (and hence is not yet participating in the trial).
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 208
197 // Return the default group name of the FieldTrial. 209 // Return the default group name of the FieldTrial.
198 std::string default_group_name() const { return default_group_name_; } 210 std::string default_group_name() const { return default_group_name_; }
199 211
200 // 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.
201 void SetGroupChoice(const std::string& name, int number); 213 void SetGroupChoice(const std::string& name, int number);
202 214
203 // Returns the group_name. A winner need not have been chosen. 215 // Returns the group_name. A winner need not have been chosen.
204 std::string group_name_internal() const { return group_name_; } 216 std::string group_name_internal() const { return group_name_; }
205 217
206 // Calculates a uniformly-distributed double between [0.0, 1.0) given
207 // a |client_id| and a |trial_name| (the latter is used as salt to avoid
208 // separate one-time randomized trials from all having the same results).
209 static double HashClientId(const std::string& client_id,
210 const std::string& trial_name);
211
212 // The name of the field trial, as can be found via the FieldTrialList. 218 // The name of the field trial, as can be found via the FieldTrialList.
213 const std::string name_; 219 const std::string name_;
214 220
215 // The maximum sum of all probabilities supplied, which corresponds to 100%. 221 // The maximum sum of all probabilities supplied, which corresponds to 100%.
216 // This is the scaling factor used to adjust supplied probabilities. 222 // This is the scaling factor used to adjust supplied probabilities.
217 const Probability divisor_; 223 const Probability divisor_;
218 224
219 // The name of the default group. 225 // The name of the default group.
220 const std::string default_group_name_; 226 const std::string default_group_name_;
221 227
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
267 static int kExpirationYearInFuture; 273 static int kExpirationYearInFuture;
268 274
269 // Observer is notified when a FieldTrial's group is selected. 275 // Observer is notified when a FieldTrial's group is selected.
270 class BASE_EXPORT Observer { 276 class BASE_EXPORT Observer {
271 public: 277 public:
272 // Notify observers when FieldTrials's group is selected. 278 // Notify observers when FieldTrials's group is selected.
273 virtual void OnFieldTrialGroupFinalized(const std::string& trial_name, 279 virtual void OnFieldTrialGroupFinalized(const std::string& trial_name,
274 const std::string& group_name) = 0; 280 const std::string& group_name) = 0;
275 281
276 protected: 282 protected:
277 virtual ~Observer() {} 283 virtual ~Observer();
278 }; 284 };
279 285
280 // This singleton holds the global list of registered FieldTrials. 286 // This singleton holds the global list of registered FieldTrials.
281 // 287 //
282 // |client_id| should be an opaque, diverse ID for this client that does not 288 // To support one-time randomized field trials, specify a non-NULL
283 // change between sessions, to enable one-time randomized trials. The empty 289 // |entropy_provider| which should be a source of uniformly distributed
284 // string may be provided, in which case one-time randomized trials will 290 // entropy values. Takes ownership of |entropy_provider|. If one time
285 // not be available. 291 // randomization is not desired, pass in NULL for |entropy_provider|.
286 explicit FieldTrialList(const std::string& client_id); 292 explicit FieldTrialList(const FieldTrial::EntropyProvider* entropy_provider);
293
287 // Destructor Release()'s references to all registered FieldTrial instances. 294 // Destructor Release()'s references to all registered FieldTrial instances.
288 ~FieldTrialList(); 295 ~FieldTrialList();
289 296
290 // Get a FieldTrial instance from the factory. 297 // Get a FieldTrial instance from the factory.
291 // 298 //
292 // |name| is used to register the instance with the FieldTrialList class, 299 // |name| is used to register the instance with the FieldTrialList class,
293 // and can be used to find the trial (only one trial can be present for each 300 // and can be used to find the trial (only one trial can be present for each
294 // name). |default_group_name| is the name of the default group which will 301 // name). |default_group_name| is the name of the default group which will
295 // be chosen if none of the subsequent appended groups get to be chosen. 302 // be chosen if none of the subsequent appended groups get to be chosen.
296 // |default_group_number| can receive the group number of the default group as 303 // |default_group_number| can receive the group number of the default group as
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
382 static TimeTicks application_start_time() { 389 static TimeTicks application_start_time() {
383 if (global_) 390 if (global_)
384 return global_->application_start_time_; 391 return global_->application_start_time_;
385 // For testing purposes only, or when we don't yet have a start time. 392 // For testing purposes only, or when we don't yet have a start time.
386 return TimeTicks::Now(); 393 return TimeTicks::Now();
387 } 394 }
388 395
389 // Return the number of active field trials. 396 // Return the number of active field trials.
390 static size_t GetFieldTrialCount(); 397 static size_t GetFieldTrialCount();
391 398
399 // If one-time randomization is enabled, returns a weak pointer to the
400 // corresponding EntropyProvider. Otherwise, returns NULL.
401 static const FieldTrial::EntropyProvider*
402 GetEntropyProviderForOneTimeRandomization();
403
392 // Returns true if you can call |FieldTrial::UseOneTimeRandomization()| 404 // Returns true if you can call |FieldTrial::UseOneTimeRandomization()|
393 // without error, i.e. if a non-empty string was provided as the client_id 405 // without error, i.e. if a non-NULL entropy provider was specified when
394 // when constructing the FieldTrialList singleton. 406 // constructing the FieldTrialList singleton.
395 static bool IsOneTimeRandomizationEnabled(); 407 static bool IsOneTimeRandomizationEnabled();
396 408
397 // Returns an opaque, diverse ID for this client that does not change
398 // between sessions.
399 //
400 // Returns the empty string if one-time randomization is not enabled.
401 static const std::string& client_id();
402
403 private: 409 private:
404 // A map from FieldTrial names to the actual instances. 410 // A map from FieldTrial names to the actual instances.
405 typedef std::map<std::string, FieldTrial*> RegistrationList; 411 typedef std::map<std::string, FieldTrial*> RegistrationList;
406 412
407 // Helper function should be called only while holding lock_. 413 // Helper function should be called only while holding lock_.
408 FieldTrial* PreLockedFind(const std::string& name); 414 FieldTrial* PreLockedFind(const std::string& name);
409 415
410 // Register() stores a pointer to the given trial in a global map. 416 // Register() stores a pointer to the given trial in a global map.
411 // This method also AddRef's the indicated trial. 417 // This method also AddRef's the indicated trial.
412 // This should always be called after creating a new FieldTrial instance. 418 // This should always be called after creating a new FieldTrial instance.
413 static void Register(FieldTrial* trial); 419 static void Register(FieldTrial* trial);
414 420
415 static FieldTrialList* global_; // The singleton of this class. 421 static FieldTrialList* global_; // The singleton of this class.
416 422
417 // This will tell us if there is an attempt to register a field 423 // This will tell us if there is an attempt to register a field
418 // trial or check if one-time randomization is enabled without 424 // trial or check if one-time randomization is enabled without
419 // creating the FieldTrialList. This is not an error, unless a 425 // creating the FieldTrialList. This is not an error, unless a
420 // FieldTrialList is created after that. 426 // FieldTrialList is created after that.
421 static bool used_without_global_; 427 static bool used_without_global_;
422 428
423 // A helper value made available to users, that shows when the FieldTrialList 429 // A helper value made available to users, that shows when the FieldTrialList
424 // was initialized. Note that this is a singleton instance, and hence is a 430 // was initialized. Note that this is a singleton instance, and hence is a
425 // good approximation to the start of the process. 431 // good approximation to the start of the process.
426 TimeTicks application_start_time_; 432 TimeTicks application_start_time_;
427 433
428 // Lock for access to registered_. 434 // Lock for access to registered_.
429 base::Lock lock_; 435 base::Lock lock_;
430 RegistrationList registered_; 436 RegistrationList registered_;
431 437
432 // An opaque, diverse ID for this client that does not change 438 // Entropy provider to be used for one-time randomized field trials. If NULL,
433 // between sessions, or the empty string if not initialized. 439 // one-time randomization is not supported.
434 std::string client_id_; 440 scoped_ptr<const FieldTrial::EntropyProvider> entropy_provider_;
435 441
436 // List of observers to be notified when a group is selected for a FieldTrial. 442 // List of observers to be notified when a group is selected for a FieldTrial.
437 scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_; 443 scoped_refptr<ObserverListThreadSafe<Observer> > observer_list_;
438 444
439 DISALLOW_COPY_AND_ASSIGN(FieldTrialList); 445 DISALLOW_COPY_AND_ASSIGN(FieldTrialList);
440 }; 446 };
441 447
442 } // namespace base 448 } // namespace base
443 449
444 #endif // BASE_METRICS_FIELD_TRIAL_H_ 450 #endif // BASE_METRICS_FIELD_TRIAL_H_
OLDNEW
« no previous file with comments | « .gitignore ('k') | base/metrics/field_trial.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698