OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 #ifndef BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ | 5 #ifndef BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ |
6 #define BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ | 6 #define BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ |
7 | 7 |
| 8 #include <map> |
8 #include <memory> | 9 #include <memory> |
9 | 10 |
10 #include "base/atomicops.h" | 11 #include "base/atomicops.h" |
11 #include "base/base_export.h" | 12 #include "base/base_export.h" |
12 #include "base/feature_list.h" | 13 #include "base/feature_list.h" |
13 #include "base/memory/shared_memory.h" | 14 #include "base/memory/shared_memory.h" |
14 #include "base/metrics/histogram_base.h" | 15 #include "base/metrics/histogram_base.h" |
15 #include "base/metrics/persistent_memory_allocator.h" | 16 #include "base/metrics/persistent_memory_allocator.h" |
16 #include "base/strings/string_piece.h" | 17 #include "base/strings/string_piece.h" |
| 18 #include "base/synchronization/lock.h" |
17 | 19 |
18 namespace base { | 20 namespace base { |
19 | 21 |
| 22 class PersistentSampleMapRecords; |
| 23 class PersistentSparseHistogramDataManager; |
| 24 |
20 // Feature definition for enabling histogram persistence. | 25 // Feature definition for enabling histogram persistence. |
21 BASE_EXPORT extern const Feature kPersistentHistogramsFeature; | 26 BASE_EXPORT extern const Feature kPersistentHistogramsFeature; |
22 | 27 |
| 28 |
| 29 // A data manager for sparse histograms so each instance of such doesn't have |
| 30 // to separately iterate over the entire memory segment. Though this class |
| 31 // will generally be accessed through the PersistentHistogramAllocator above, |
| 32 // it can be used independently on any PersistentMemoryAllocator (making it |
| 33 // useable for testing). This object supports only one instance of a sparse |
| 34 // histogram for a given id. Tests that create multiple identical histograms, |
| 35 // perhaps to simulate multiple processes, should create a separate manager |
| 36 // for each. |
| 37 class BASE_EXPORT PersistentSparseHistogramDataManager { |
| 38 public: |
| 39 // Constructs the data manager. The allocator must live longer than any |
| 40 // managers that reference it. |
| 41 explicit PersistentSparseHistogramDataManager( |
| 42 PersistentMemoryAllocator* allocator); |
| 43 |
| 44 ~PersistentSparseHistogramDataManager(); |
| 45 |
| 46 // Returns the object that manages the persistent-sample-map records for a |
| 47 // given |id|. Only one |user| of this data is allowed at a time. This does |
| 48 // an automatic Acquire() on the records. The user must call Release() on |
| 49 // the returned object when it is finished with it. Ownership of the records |
| 50 // object stays with this manager. |
| 51 PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id, |
| 52 const void* user); |
| 53 |
| 54 // Convenience method that gets the object for a given reference so callers |
| 55 // don't have to also keep their own pointer to the appropriate allocator. |
| 56 template <typename T> |
| 57 T* GetAsObject(PersistentMemoryAllocator::Reference ref, uint32_t type_id) { |
| 58 return allocator_->GetAsObject<T>(ref, type_id); |
| 59 } |
| 60 |
| 61 private: |
| 62 friend class PersistentSampleMapRecords; |
| 63 |
| 64 // Gets the object holding records for a given sample-map id when |lock_| |
| 65 // has already been acquired. |
| 66 PersistentSampleMapRecords* GetSampleMapRecordsWhileLocked(uint64_t id); |
| 67 |
| 68 // Loads sample-map records looking for those belonging to the specified |
| 69 // |load_id|. Records found for other sample-maps are held for later use |
| 70 // without having to iterate again. This should be called only from a |
| 71 // PersistentSampleMapRecords object because those objects have a contract |
| 72 // that there are no other threads accessing the internal records_ field |
| 73 // of the object that is passed in. |
| 74 bool LoadRecords(PersistentSampleMapRecords* sample_map_records); |
| 75 |
| 76 // Weak-pointer to the allocator used by the sparse histograms. |
| 77 PersistentMemoryAllocator* allocator_; |
| 78 |
| 79 // Iterator within the allocator for finding sample records. |
| 80 PersistentMemoryAllocator::Iterator record_iterator_; |
| 81 |
| 82 // Mapping of sample-map IDs to their sample records. |
| 83 std::map<uint64_t, std::unique_ptr<PersistentSampleMapRecords>> |
| 84 sample_records_; |
| 85 |
| 86 // A lock used for synchronizing changes to sample_records_. |
| 87 base::Lock lock_; |
| 88 |
| 89 DISALLOW_COPY_AND_ASSIGN(PersistentSparseHistogramDataManager); |
| 90 }; |
| 91 |
| 92 |
| 93 // This class manages sample-records used by a PersistentSampleMap container |
| 94 // that underlies a persistent SparseHistogram object. It is broken out into a |
| 95 // top-level class so that it can be forward-declared in other header files |
| 96 // rather than include this entire file as would be necessary if it were |
| 97 // declared within the PersistentSparseHistogramDataManager class above. |
| 98 class BASE_EXPORT PersistentSampleMapRecords { |
| 99 public: |
| 100 // Constructs an instance of this class. The manager object must live longer |
| 101 // than all instances of this class that reference it, which is not usually |
| 102 // a problem since these objects are generally managed from within that |
| 103 // manager instance. |
| 104 PersistentSampleMapRecords(PersistentSparseHistogramDataManager* data_manager, |
| 105 uint64_t sample_map_id); |
| 106 |
| 107 ~PersistentSampleMapRecords(); |
| 108 |
| 109 // Resets the internal state for a new object using this data. The return |
| 110 // value is "this" as a convenience. |
| 111 PersistentSampleMapRecords* Acquire(const void* user); |
| 112 |
| 113 // Indicates that the using object is done with this data. |
| 114 void Release(const void* user); |
| 115 |
| 116 // Gets the next reference to a persistent sample-map record. The type and |
| 117 // layout of the data being referenced is defined entirely within the |
| 118 // PersistentSampleMap class. |
| 119 PersistentMemoryAllocator::Reference GetNext(); |
| 120 |
| 121 // Creates a new persistent sample-map record for sample |value| and returns |
| 122 // a reference to it. |
| 123 PersistentMemoryAllocator::Reference CreateNew(HistogramBase::Sample value); |
| 124 |
| 125 // Convenience method that gets the object for a given reference so callers |
| 126 // don't have to also keep their own pointer to the appropriate allocator. |
| 127 // This is expected to be used with the SampleRecord structure defined inside |
| 128 // the persistent_sample_map.cc file but since that isn't exported (for |
| 129 // cleanliness of the interface), a template is defined that will be |
| 130 // resolved when used inside that file. |
| 131 template <typename T> |
| 132 T* GetAsObject(PersistentMemoryAllocator::Reference ref, uint32_t type_id) { |
| 133 return data_manager_->GetAsObject<T>(ref, type_id); |
| 134 } |
| 135 |
| 136 private: |
| 137 friend PersistentSparseHistogramDataManager; |
| 138 |
| 139 // Weak-pointer to the parent data-manager object. |
| 140 PersistentSparseHistogramDataManager* data_manager_; |
| 141 |
| 142 // ID of PersistentSampleMap to which these records apply. |
| 143 const uint64_t sample_map_id_; |
| 144 |
| 145 // The current user of this set of records. It is used to ensure that no |
| 146 // more than one object is using these records at a given time. |
| 147 const void* user_ = nullptr; |
| 148 |
| 149 // This is the count of how many "records" have already been read by the |
| 150 // owning sample-map. |
| 151 size_t seen_ = 0; |
| 152 |
| 153 // This is the set of records previously found for a sample map. Because |
| 154 // there is ever only one object with a given ID (typically a hash of a |
| 155 // histogram name) and because the parent SparseHistogram has acquired |
| 156 // its own lock before accessing the PersistentSampleMap it controls, this |
| 157 // list can be accessed without acquiring any additional lock. |
| 158 std::vector<PersistentMemoryAllocator::Reference> records_; |
| 159 |
| 160 // This is the set of records found during iteration through memory. It |
| 161 // is appended in bulk to "records". Access to this vector can be done |
| 162 // only while holding the parent manager's lock. |
| 163 std::vector<PersistentMemoryAllocator::Reference> found_; |
| 164 |
| 165 DISALLOW_COPY_AND_ASSIGN(PersistentSampleMapRecords); |
| 166 }; |
| 167 |
| 168 |
23 // This class manages histograms created within a PersistentMemoryAllocator. | 169 // This class manages histograms created within a PersistentMemoryAllocator. |
24 class BASE_EXPORT PersistentHistogramAllocator { | 170 class BASE_EXPORT PersistentHistogramAllocator { |
25 public: | 171 public: |
26 // A reference to a histogram. While this is implemented as PMA::Reference, | 172 // A reference to a histogram. While this is implemented as PMA::Reference, |
27 // it is not conceptually the same thing. Outside callers should always use | 173 // it is not conceptually the same thing. Outside callers should always use |
28 // a Reference matching the class it is for and not mix the two. | 174 // a Reference matching the class it is for and not mix the two. |
29 using Reference = PersistentMemoryAllocator::Reference; | 175 using Reference = PersistentMemoryAllocator::Reference; |
30 | 176 |
31 // Iterator used for fetching persistent histograms from an allocator. | 177 // Iterator used for fetching persistent histograms from an allocator. |
32 // It is lock-free and thread-safe. | 178 // It is lock-free and thread-safe. |
(...skipping 19 matching lines...) Expand all Loading... |
52 | 198 |
53 // The iterator used for stepping through objects in persistent memory. | 199 // The iterator used for stepping through objects in persistent memory. |
54 // It is lock-free and thread-safe which is why this class is also such. | 200 // It is lock-free and thread-safe which is why this class is also such. |
55 PersistentMemoryAllocator::Iterator memory_iter_; | 201 PersistentMemoryAllocator::Iterator memory_iter_; |
56 | 202 |
57 DISALLOW_COPY_AND_ASSIGN(Iterator); | 203 DISALLOW_COPY_AND_ASSIGN(Iterator); |
58 }; | 204 }; |
59 | 205 |
60 // A PersistentHistogramAllocator is constructed from a PersistentMemory- | 206 // A PersistentHistogramAllocator is constructed from a PersistentMemory- |
61 // Allocator object of which it takes ownership. | 207 // Allocator object of which it takes ownership. |
62 PersistentHistogramAllocator( | 208 explicit PersistentHistogramAllocator( |
63 std::unique_ptr<PersistentMemoryAllocator> memory); | 209 std::unique_ptr<PersistentMemoryAllocator> memory); |
64 virtual ~PersistentHistogramAllocator(); | 210 virtual ~PersistentHistogramAllocator(); |
65 | 211 |
66 // Direct access to underlying memory allocator. If the segment is shared | 212 // Direct access to underlying memory allocator. If the segment is shared |
67 // across threads or processes, reading data through these values does | 213 // across threads or processes, reading data through these values does |
68 // not guarantee consistency. Use with care. Do not write. | 214 // not guarantee consistency. Use with care. Do not write. |
69 PersistentMemoryAllocator* memory_allocator() { | 215 PersistentMemoryAllocator* memory_allocator() { |
70 return memory_allocator_.get(); | 216 return memory_allocator_.get(); |
71 } | 217 } |
72 | 218 |
(...skipping 21 matching lines...) Expand all Loading... |
94 int maximum, | 240 int maximum, |
95 const BucketRanges* bucket_ranges, | 241 const BucketRanges* bucket_ranges, |
96 int32_t flags, | 242 int32_t flags, |
97 Reference* ref_ptr); | 243 Reference* ref_ptr); |
98 | 244 |
99 // Finalize the creation of the histogram, making it available to other | 245 // Finalize the creation of the histogram, making it available to other |
100 // processes if |registered| (as in: added to the StatisticsRecorder) is | 246 // processes if |registered| (as in: added to the StatisticsRecorder) is |
101 // True, forgetting it otherwise. | 247 // True, forgetting it otherwise. |
102 void FinalizeHistogram(Reference ref, bool registered); | 248 void FinalizeHistogram(Reference ref, bool registered); |
103 | 249 |
| 250 // Returns the object that manages the persistent-sample-map records for a |
| 251 // given |id|. Only one |user| of this data is allowed at a time. This does |
| 252 // an automatic Acquire() on the records. The user must call Release() on |
| 253 // the returned object when it is finished with it. Ownership stays with |
| 254 // this allocator. |
| 255 PersistentSampleMapRecords* UseSampleMapRecords(uint64_t id, |
| 256 const void* user); |
| 257 |
104 // Create internal histograms for tracking memory use and allocation sizes | 258 // Create internal histograms for tracking memory use and allocation sizes |
105 // for allocator of |name| (which can simply be the result of Name()). This | 259 // for allocator of |name| (which can simply be the result of Name()). This |
106 // is done seperately from construction for situations such as when the | 260 // is done seperately from construction for situations such as when the |
107 // histograms will be backed by memory provided by this very allocator. | 261 // histograms will be backed by memory provided by this very allocator. |
108 // | 262 // |
109 // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml | 263 // IMPORTANT: Callers must update tools/metrics/histograms/histograms.xml |
110 // with the following histograms: | 264 // with the following histograms: |
111 // UMA.PersistentAllocator.name.Allocs | 265 // UMA.PersistentAllocator.name.Allocs |
112 // UMA.PersistentAllocator.name.UsedPct | 266 // UMA.PersistentAllocator.name.UsedPct |
113 void CreateTrackingHistograms(StringPiece name); | 267 void CreateTrackingHistograms(StringPiece name); |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 // Create a histogram based on saved (persistent) information about it. | 326 // Create a histogram based on saved (persistent) information about it. |
173 std::unique_ptr<HistogramBase> CreateHistogram( | 327 std::unique_ptr<HistogramBase> CreateHistogram( |
174 PersistentHistogramData* histogram_data_ptr); | 328 PersistentHistogramData* histogram_data_ptr); |
175 | 329 |
176 // Record the result of a histogram creation. | 330 // Record the result of a histogram creation. |
177 static void RecordCreateHistogramResult(CreateHistogramResultType result); | 331 static void RecordCreateHistogramResult(CreateHistogramResultType result); |
178 | 332 |
179 // The memory allocator that provides the actual histogram storage. | 333 // The memory allocator that provides the actual histogram storage. |
180 std::unique_ptr<PersistentMemoryAllocator> memory_allocator_; | 334 std::unique_ptr<PersistentMemoryAllocator> memory_allocator_; |
181 | 335 |
| 336 // The data-manager used to improve performance of sparse histograms. |
| 337 PersistentSparseHistogramDataManager sparse_histogram_data_manager_; |
| 338 |
182 // A reference to the last-created histogram in the allocator, used to avoid | 339 // A reference to the last-created histogram in the allocator, used to avoid |
183 // trying to import what was just created. | 340 // trying to import what was just created. |
184 // TODO(bcwhite): Change this to std::atomic<PMA::Reference> when available. | 341 // TODO(bcwhite): Change this to std::atomic<PMA::Reference> when available. |
185 subtle::Atomic32 last_created_ = 0; | 342 subtle::Atomic32 last_created_ = 0; |
186 | 343 |
187 DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocator); | 344 DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocator); |
188 }; | 345 }; |
189 | 346 |
190 | 347 |
191 // A special case of the PersistentHistogramAllocator that operates on a | 348 // A special case of the PersistentHistogramAllocator that operates on a |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
258 // Import always continues from where it left off, making use of a single | 415 // Import always continues from where it left off, making use of a single |
259 // iterator to continue the work. | 416 // iterator to continue the work. |
260 Iterator import_iterator_; | 417 Iterator import_iterator_; |
261 | 418 |
262 DISALLOW_COPY_AND_ASSIGN(GlobalHistogramAllocator); | 419 DISALLOW_COPY_AND_ASSIGN(GlobalHistogramAllocator); |
263 }; | 420 }; |
264 | 421 |
265 } // namespace base | 422 } // namespace base |
266 | 423 |
267 #endif // BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ | 424 #endif // BASE_METRICS_HISTOGRAM_PERSISTENCE_H_ |
OLD | NEW |