 Chromium Code Reviews
 Chromium Code Reviews Issue 2560723004:
  Add field trial dump and retrieval methods from shared memory  (Closed)
    
  
    Issue 2560723004:
  Add field trial dump and retrieval methods from shared memory  (Closed) 
  | OLD | NEW | 
|---|---|
| 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 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 66 #include "base/base_export.h" | 66 #include "base/base_export.h" | 
| 67 #include "base/command_line.h" | 67 #include "base/command_line.h" | 
| 68 #include "base/feature_list.h" | 68 #include "base/feature_list.h" | 
| 69 #include "base/files/file.h" | 69 #include "base/files/file.h" | 
| 70 #include "base/gtest_prod_util.h" | 70 #include "base/gtest_prod_util.h" | 
| 71 #include "base/macros.h" | 71 #include "base/macros.h" | 
| 72 #include "base/memory/ref_counted.h" | 72 #include "base/memory/ref_counted.h" | 
| 73 #include "base/memory/shared_memory.h" | 73 #include "base/memory/shared_memory.h" | 
| 74 #include "base/metrics/persistent_memory_allocator.h" | 74 #include "base/metrics/persistent_memory_allocator.h" | 
| 75 #include "base/observer_list_threadsafe.h" | 75 #include "base/observer_list_threadsafe.h" | 
| 76 #include "base/pickle.h" | |
| 76 #include "base/process/launch.h" | 77 #include "base/process/launch.h" | 
| 77 #include "base/strings/string_piece.h" | 78 #include "base/strings/string_piece.h" | 
| 78 #include "base/synchronization/lock.h" | 79 #include "base/synchronization/lock.h" | 
| 79 #include "base/time/time.h" | 80 #include "base/time/time.h" | 
| 80 | 81 | 
| 81 namespace base { | 82 namespace base { | 
| 82 | 83 | 
| 83 class FieldTrialList; | 84 class FieldTrialList; | 
| 84 | 85 | 
| 85 class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> { | 86 class BASE_EXPORT FieldTrial : public RefCounted<FieldTrial> { | 
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 126 struct BASE_EXPORT State { | 127 struct BASE_EXPORT State { | 
| 127 StringPiece trial_name; | 128 StringPiece trial_name; | 
| 128 StringPiece group_name; | 129 StringPiece group_name; | 
| 129 bool activated; | 130 bool activated; | 
| 130 | 131 | 
| 131 State(); | 132 State(); | 
| 132 State(const State& other); | 133 State(const State& other); | 
| 133 ~State(); | 134 ~State(); | 
| 134 }; | 135 }; | 
| 135 | 136 | 
| 137 // We create one FieldTrialEntry per field trial in shared memory, via | |
| 138 // AddToAllocatorWhileLocked. The FieldTrialEntry is followed by a | |
| 139 // base::Pickle object that we unpickle and read from. Any changes to this | |
| 140 // structure requires a bump in kFieldTrialType id defined above. | |
| 
manzagop (departed)
2016/12/09 21:22:24
nit: update comment as kFieldTrialType is defined
 
lawrencewu
2016/12/09 22:20:49
Done.
 | |
| 141 struct FieldTrialEntry { | |
| 142 // Expected size for 32/64-bit check. | |
| 143 static constexpr size_t kExpectedInstanceSize = 8; | |
| 144 | |
| 145 // Whether or not this field trial is activated. This is really just a | |
| 146 // boolean but marked as a uint32_t for portability reasons. | |
| 147 uint32_t activated; | |
| 148 | |
| 149 // Size of the pickled structure, NOT the total size of this entry. | |
| 150 uint32_t pickle_size; | |
| 151 | |
| 152 // Calling this is only valid when the entry is initialized. That is, it | |
| 153 // resides in shared memory and has a pickle containing the trial name and | |
| 154 // group name following it. | |
| 155 bool GetTrialAndGroupName(StringPiece* trial_name, | |
| 156 StringPiece* group_name) const; | |
| 157 | |
| 158 // Calling this is only valid when the entry is initialized as well. Reads | |
| 159 // the parameters following the trial and group name and stores them as | |
| 160 // key-value mappings in |params|. | |
| 161 bool GetParams(std::map<std::string, std::string>* params) const; | |
| 162 | |
| 163 private: | |
| 164 // Returns an iterator over the data containing names and params. | |
| 165 PickleIterator GetPickleIterator() const; | |
| 166 | |
| 167 // Takes the iterator and writes out the first two items into |trial_name| | |
| 168 // and |group_name|. | |
| 169 bool ReadStringPair(PickleIterator* iter, | |
| 170 StringPiece* trial_name, | |
| 171 StringPiece* group_name) const; | |
| 172 }; | |
| 
Alexei Svitkine (slow)
2016/12/09 20:08:43
Nit: Add DISALLOW_COPY_AND_ASSIGN(FieldTrialEntry)
 
bcwhite
2016/12/09 20:13:29
Allocator objects are always POD so can always be
 
manzagop (departed)
2016/12/09 21:22:24
Drive by: if relying on POD / trivial copy, use a
 
bcwhite
2016/12/09 21:38:42
Already exists.  See PersistentMemoryAllocator::Ge
 | |
| 173 | |
| 136 typedef std::vector<ActiveGroup> ActiveGroups; | 174 typedef std::vector<ActiveGroup> ActiveGroups; | 
| 137 | 175 | 
| 138 // A return value to indicate that a given instance has not yet had a group | 176 // A return value to indicate that a given instance has not yet had a group | 
| 139 // assignment (and hence is not yet participating in the trial). | 177 // assignment (and hence is not yet participating in the trial). | 
| 140 static const int kNotFinalized; | 178 static const int kNotFinalized; | 
| 141 | 179 | 
| 142 // Disables this trial, meaning it always determines the default group | 180 // Disables this trial, meaning it always determines the default group | 
| 143 // has been selected. May be called immediately after construction, or | 181 // has been selected. May be called immediately after construction, or | 
| 144 // at any time after initialization (should not be interleaved with | 182 // at any time after initialization (should not be interleaved with | 
| 145 // AppendGroup calls). Once disabled, there is no way to re-enable a | 183 // AppendGroup calls). Once disabled, there is no way to re-enable a | 
| (...skipping 424 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 570 // Gets the parameters for |field_trial| from shared memory and stores them in | 608 // Gets the parameters for |field_trial| from shared memory and stores them in | 
| 571 // |params|. This is only exposed for use by FieldTrialParamAssociator and | 609 // |params|. This is only exposed for use by FieldTrialParamAssociator and | 
| 572 // shouldn't be used by anything else. | 610 // shouldn't be used by anything else. | 
| 573 static bool GetParamsFromSharedMemory( | 611 static bool GetParamsFromSharedMemory( | 
| 574 FieldTrial* field_trial, | 612 FieldTrial* field_trial, | 
| 575 std::map<std::string, std::string>* params); | 613 std::map<std::string, std::string>* params); | 
| 576 | 614 | 
| 577 // Clears all the params in the allocator. | 615 // Clears all the params in the allocator. | 
| 578 static void ClearParamsFromSharedMemoryForTesting(); | 616 static void ClearParamsFromSharedMemoryForTesting(); | 
| 579 | 617 | 
| 618 // We want to be able to dump field trial state to an allocator so that it | |
| 
Alexei Svitkine (slow)
2016/12/09 20:08:43
Nit: Can you rephrase this comment and the one bel
 
lawrencewu
2016/12/09 20:31:11
Done (as well as below).
 | |
| 619 // can be analyzed after a crash. | |
| 620 static void DumpAllFieldTrialsToPersistentAllocator( | |
| 621 PersistentMemoryAllocator* allocator); | |
| 622 | |
| 623 // We want to be able to retrieve field trial state from an allocator so that | |
| 624 // it can be analyzed after a crash. The pointers in the returned vector are | |
| 625 // into the persistent memory segment and so are only valid as long as the | |
| 626 // allocator is valid. | |
| 627 static std::vector<const FieldTrial::FieldTrialEntry*> | |
| 628 GetAllFieldTrialsFromPersistentAllocator( | |
| 629 const PersistentMemoryAllocator* allocator); | |
| 
Alexei Svitkine (slow)
2016/12/09 20:08:43
Can this be passed by const& instead of const*?
 
lawrencewu
2016/12/09 20:31:11
Done.
 | |
| 630 | |
| 580 private: | 631 private: | 
| 581 // Allow tests to access our innards for testing purposes. | 632 // Allow tests to access our innards for testing purposes. | 
| 582 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, InstantiateAllocator); | 633 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, InstantiateAllocator); | 
| 583 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, AddTrialsToAllocator); | 634 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, AddTrialsToAllocator); | 
| 584 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, | 635 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, | 
| 585 DoNotAddSimulatedFieldTrialsToAllocator); | 636 DoNotAddSimulatedFieldTrialsToAllocator); | 
| 586 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, AssociateFieldTrialParams); | 637 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, AssociateFieldTrialParams); | 
| 587 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, ClearParamsFromSharedMemory); | 638 FRIEND_TEST_ALL_PREFIXES(FieldTrialListTest, ClearParamsFromSharedMemory); | 
| 588 | 639 | 
| 589 #if defined(OS_WIN) | 640 #if defined(OS_WIN) | 
| (...skipping 23 matching lines...) Expand all Loading... | |
| 613 static bool CreateTrialsFromSharedMemory( | 664 static bool CreateTrialsFromSharedMemory( | 
| 614 std::unique_ptr<base::SharedMemory> shm); | 665 std::unique_ptr<base::SharedMemory> shm); | 
| 615 | 666 | 
| 616 // Instantiate the field trial allocator, add all existing field trials to it, | 667 // Instantiate the field trial allocator, add all existing field trials to it, | 
| 617 // and duplicates its handle to a read-only handle, which gets stored in | 668 // and duplicates its handle to a read-only handle, which gets stored in | 
| 618 // |readonly_allocator_handle|. | 669 // |readonly_allocator_handle|. | 
| 619 static void InstantiateFieldTrialAllocatorIfNeeded(); | 670 static void InstantiateFieldTrialAllocatorIfNeeded(); | 
| 620 | 671 | 
| 621 // Adds the field trial to the allocator. Caller must hold a lock before | 672 // Adds the field trial to the allocator. Caller must hold a lock before | 
| 622 // calling this. | 673 // calling this. | 
| 623 static void AddToAllocatorWhileLocked(FieldTrial* field_trial); | 674 static void AddToAllocatorWhileLocked(PersistentMemoryAllocator* allocator, | 
| 675 FieldTrial* field_trial); | |
| 624 | 676 | 
| 625 // Activate the corresponding field trial entry struct in shared memory. | 677 // Activate the corresponding field trial entry struct in shared memory. | 
| 626 static void ActivateFieldTrialEntryWhileLocked(FieldTrial* field_trial); | 678 static void ActivateFieldTrialEntryWhileLocked(FieldTrial* field_trial); | 
| 627 | 679 | 
| 628 // A map from FieldTrial names to the actual instances. | 680 // A map from FieldTrial names to the actual instances. | 
| 629 typedef std::map<std::string, FieldTrial*> RegistrationMap; | 681 typedef std::map<std::string, FieldTrial*> RegistrationMap; | 
| 630 | 682 | 
| 631 // If one-time randomization is enabled, returns a weak pointer to the | 683 // If one-time randomization is enabled, returns a weak pointer to the | 
| 632 // corresponding EntropyProvider. Otherwise, returns NULL. | 684 // corresponding EntropyProvider. Otherwise, returns NULL. | 
| 633 static const FieldTrial::EntropyProvider* | 685 static const FieldTrial::EntropyProvider* | 
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 675 | 727 | 
| 676 // Tracks whether CreateTrialsFromCommandLine() has been called. | 728 // Tracks whether CreateTrialsFromCommandLine() has been called. | 
| 677 bool create_trials_from_command_line_called_ = false; | 729 bool create_trials_from_command_line_called_ = false; | 
| 678 | 730 | 
| 679 DISALLOW_COPY_AND_ASSIGN(FieldTrialList); | 731 DISALLOW_COPY_AND_ASSIGN(FieldTrialList); | 
| 680 }; | 732 }; | 
| 681 | 733 | 
| 682 } // namespace base | 734 } // namespace base | 
| 683 | 735 | 
| 684 #endif // BASE_METRICS_FIELD_TRIAL_H_ | 736 #endif // BASE_METRICS_FIELD_TRIAL_H_ | 
| OLD | NEW |