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 #include "base/metrics/persistent_sample_map.h" | 5 #include "base/metrics/persistent_sample_map.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
9 #include "base/metrics/persistent_histogram_allocator.h" | 9 #include "base/metrics/persistent_histogram_allocator.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 void PersistentSampleMapIterator::SkipEmptyBuckets() { | 75 void PersistentSampleMapIterator::SkipEmptyBuckets() { |
76 while (!Done() && *iter_->second == 0) { | 76 while (!Done() && *iter_->second == 0) { |
77 ++iter_; | 77 ++iter_; |
78 } | 78 } |
79 } | 79 } |
80 | 80 |
81 // This structure holds an entry for a PersistentSampleMap within a persistent | 81 // This structure holds an entry for a PersistentSampleMap within a persistent |
82 // memory allocator. The "id" must be unique across all maps held by an | 82 // memory allocator. The "id" must be unique across all maps held by an |
83 // allocator or they will get attached to the wrong sample map. | 83 // allocator or they will get attached to the wrong sample map. |
84 struct SampleRecord { | 84 struct SampleRecord { |
| 85 // SHA1(SampleRecord): Increment this if structure changes! |
| 86 static constexpr uint32_t kPersistentTypeId = 0x8FE6A69F + 1; |
| 87 |
85 // Expected size for 32/64-bit check. | 88 // Expected size for 32/64-bit check. |
86 static constexpr size_t kExpectedInstanceSize = 16; | 89 static constexpr size_t kExpectedInstanceSize = 16; |
87 | 90 |
88 uint64_t id; // Unique identifier of owner. | 91 uint64_t id; // Unique identifier of owner. |
89 Sample value; // The value for which this record holds a count. | 92 Sample value; // The value for which this record holds a count. |
90 Count count; // The count associated with the above value. | 93 Count count; // The count associated with the above value. |
91 }; | 94 }; |
92 | 95 |
93 // The type-id used to identify sample records inside an allocator. | |
94 const uint32_t kTypeIdSampleRecord = 0x8FE6A69F + 1; // SHA1(SampleRecord) v1 | |
95 | |
96 } // namespace | 96 } // namespace |
97 | 97 |
98 PersistentSampleMap::PersistentSampleMap( | 98 PersistentSampleMap::PersistentSampleMap( |
99 uint64_t id, | 99 uint64_t id, |
100 PersistentHistogramAllocator* allocator, | 100 PersistentHistogramAllocator* allocator, |
101 Metadata* meta) | 101 Metadata* meta) |
102 : HistogramSamples(id, meta), allocator_(allocator) {} | 102 : HistogramSamples(id, meta), allocator_(allocator) {} |
103 | 103 |
104 PersistentSampleMap::~PersistentSampleMap() { | 104 PersistentSampleMap::~PersistentSampleMap() { |
105 if (records_) | 105 if (records_) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
137 // loaded before trying to iterate over the map. | 137 // loaded before trying to iterate over the map. |
138 const_cast<PersistentSampleMap*>(this)->ImportSamples(-1, true); | 138 const_cast<PersistentSampleMap*>(this)->ImportSamples(-1, true); |
139 return WrapUnique(new PersistentSampleMapIterator(sample_counts_)); | 139 return WrapUnique(new PersistentSampleMapIterator(sample_counts_)); |
140 } | 140 } |
141 | 141 |
142 // static | 142 // static |
143 PersistentMemoryAllocator::Reference | 143 PersistentMemoryAllocator::Reference |
144 PersistentSampleMap::GetNextPersistentRecord( | 144 PersistentSampleMap::GetNextPersistentRecord( |
145 PersistentMemoryAllocator::Iterator& iterator, | 145 PersistentMemoryAllocator::Iterator& iterator, |
146 uint64_t* sample_map_id) { | 146 uint64_t* sample_map_id) { |
147 PersistentMemoryAllocator::Reference ref = | 147 const SampleRecord* record = iterator.GetNextOfObject<SampleRecord>(); |
148 iterator.GetNextOfType(kTypeIdSampleRecord); | |
149 const SampleRecord* record = | |
150 iterator.GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord); | |
151 if (!record) | 148 if (!record) |
152 return 0; | 149 return 0; |
153 | 150 |
154 *sample_map_id = record->id; | 151 *sample_map_id = record->id; |
155 return ref; | 152 return iterator.GetAsReference(record); |
156 } | 153 } |
157 | 154 |
158 // static | 155 // static |
159 PersistentMemoryAllocator::Reference | 156 PersistentMemoryAllocator::Reference |
160 PersistentSampleMap::CreatePersistentRecord( | 157 PersistentSampleMap::CreatePersistentRecord( |
161 PersistentMemoryAllocator* allocator, | 158 PersistentMemoryAllocator* allocator, |
162 uint64_t sample_map_id, | 159 uint64_t sample_map_id, |
163 Sample value) { | 160 Sample value) { |
164 PersistentMemoryAllocator::Reference ref = | 161 SampleRecord* record = allocator->AllocateObject<SampleRecord>(); |
165 allocator->Allocate(sizeof(SampleRecord), kTypeIdSampleRecord); | |
166 SampleRecord* record = | |
167 allocator->GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord); | |
168 | |
169 if (!record) { | 162 if (!record) { |
170 NOTREACHED() << "full=" << allocator->IsFull() | 163 NOTREACHED() << "full=" << allocator->IsFull() |
171 << ", corrupt=" << allocator->IsCorrupt(); | 164 << ", corrupt=" << allocator->IsCorrupt(); |
172 return 0; | 165 return 0; |
173 } | 166 } |
174 | 167 |
175 record->id = sample_map_id; | 168 record->id = sample_map_id; |
176 record->value = value; | 169 record->value = value; |
177 record->count = 0; | 170 record->count = 0; |
| 171 |
| 172 PersistentMemoryAllocator::Reference ref = allocator->GetAsReference(record); |
178 allocator->MakeIterable(ref); | 173 allocator->MakeIterable(ref); |
179 return ref; | 174 return ref; |
180 } | 175 } |
181 | 176 |
182 bool PersistentSampleMap::AddSubtractImpl(SampleCountIterator* iter, | 177 bool PersistentSampleMap::AddSubtractImpl(SampleCountIterator* iter, |
183 Operator op) { | 178 Operator op) { |
184 Sample min; | 179 Sample min; |
185 Sample max; | 180 Sample max; |
186 Count count; | 181 Count count; |
187 for (; !iter->Done(); iter->Next()) { | 182 for (; !iter->Done(); iter->Next()) { |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
249 records_ = allocator_->UseSampleMapRecords(id(), this); | 244 records_ = allocator_->UseSampleMapRecords(id(), this); |
250 return records_; | 245 return records_; |
251 } | 246 } |
252 | 247 |
253 Count* PersistentSampleMap::ImportSamples(Sample until_value, | 248 Count* PersistentSampleMap::ImportSamples(Sample until_value, |
254 bool import_everything) { | 249 bool import_everything) { |
255 Count* found_count = nullptr; | 250 Count* found_count = nullptr; |
256 PersistentMemoryAllocator::Reference ref; | 251 PersistentMemoryAllocator::Reference ref; |
257 PersistentSampleMapRecords* records = GetRecords(); | 252 PersistentSampleMapRecords* records = GetRecords(); |
258 while ((ref = records->GetNext()) != 0) { | 253 while ((ref = records->GetNext()) != 0) { |
259 SampleRecord* record = | 254 SampleRecord* record = records->GetAsObject<SampleRecord>(ref); |
260 records->GetAsObject<SampleRecord>(ref, kTypeIdSampleRecord); | |
261 if (!record) | 255 if (!record) |
262 continue; | 256 continue; |
263 | 257 |
264 DCHECK_EQ(id(), record->id); | 258 DCHECK_EQ(id(), record->id); |
265 | 259 |
266 // Check if the record's value is already known. | 260 // Check if the record's value is already known. |
267 if (!ContainsKey(sample_counts_, record->value)) { | 261 if (!ContainsKey(sample_counts_, record->value)) { |
268 // No: Add it to map of known values. | 262 // No: Add it to map of known values. |
269 sample_counts_[record->value] = &record->count; | 263 sample_counts_[record->value] = &record->count; |
270 } else { | 264 } else { |
(...skipping 12 matching lines...) Expand all Loading... |
283 found_count = &record->count; | 277 found_count = &record->count; |
284 if (!import_everything) | 278 if (!import_everything) |
285 break; | 279 break; |
286 } | 280 } |
287 } | 281 } |
288 | 282 |
289 return found_count; | 283 return found_count; |
290 } | 284 } |
291 | 285 |
292 } // namespace base | 286 } // namespace base |
OLD | NEW |