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

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

Issue 1840843004: Improve efficiency of persistent sparse histograms. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@improved-pma-iterator
Patch Set: added comment clarifying loop behavior Created 4 years, 8 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
« no previous file with comments | « no previous file | base/metrics/persistent_histogram_allocator.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 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
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | base/metrics/persistent_histogram_allocator.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698