OLD | NEW |
1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "components/metrics/persistent_system_profile.h" | 5 #include "components/metrics/persistent_system_profile.h" |
6 | 6 |
7 #include "base/atomicops.h" | 7 #include "base/atomicops.h" |
8 #include "base/memory/singleton.h" | 8 #include "base/memory/singleton.h" |
9 #include "base/metrics/persistent_memory_allocator.h" | 9 #include "base/metrics/persistent_memory_allocator.h" |
10 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
(...skipping 28 matching lines...) Expand all Loading... |
39 return (data_amount + sizeof(RecordHeader) + sizeof(RecordHeader) - 1) & | 39 return (data_amount + sizeof(RecordHeader) + sizeof(RecordHeader) - 1) & |
40 ~(sizeof(RecordHeader) - 1); | 40 ~(sizeof(RecordHeader) - 1); |
41 } | 41 } |
42 | 42 |
43 } // namespace | 43 } // namespace |
44 | 44 |
45 PersistentSystemProfile::RecordAllocator::RecordAllocator( | 45 PersistentSystemProfile::RecordAllocator::RecordAllocator( |
46 base::PersistentMemoryAllocator* memory_allocator, | 46 base::PersistentMemoryAllocator* memory_allocator, |
47 size_t min_size) | 47 size_t min_size) |
48 : allocator_(memory_allocator), | 48 : allocator_(memory_allocator), |
| 49 has_complete_profile_(false), |
49 alloc_reference_(0), | 50 alloc_reference_(0), |
50 alloc_size_(0), | 51 alloc_size_(0), |
51 end_offset_(0) { | 52 end_offset_(0) { |
52 AddSegment(min_size); | 53 AddSegment(min_size); |
53 } | 54 } |
54 | 55 |
55 PersistentSystemProfile::RecordAllocator::RecordAllocator( | 56 PersistentSystemProfile::RecordAllocator::RecordAllocator( |
56 const base::PersistentMemoryAllocator* memory_allocator) | 57 const base::PersistentMemoryAllocator* memory_allocator) |
57 : allocator_( | 58 : allocator_( |
58 const_cast<base::PersistentMemoryAllocator*>(memory_allocator)), | 59 const_cast<base::PersistentMemoryAllocator*>(memory_allocator)), |
59 alloc_reference_(0), | 60 alloc_reference_(0), |
60 alloc_size_(0), | 61 alloc_size_(0), |
61 end_offset_(0) {} | 62 end_offset_(0) {} |
62 | 63 |
63 void PersistentSystemProfile::RecordAllocator::Reset() { | 64 void PersistentSystemProfile::RecordAllocator::Reset() { |
64 // Clear the first word of all blocks so they're known to be "empty". | 65 // Clear the first word of all blocks so they're known to be "empty". |
65 alloc_reference_ = 0; | 66 alloc_reference_ = 0; |
66 while (NextSegment()) { | 67 while (NextSegment()) { |
67 // Get the block as a char* and cast it. It can't be fetched directly as | 68 // Get the block as a char* and cast it. It can't be fetched directly as |
68 // an array of RecordHeader because that's not a fundamental type and only | 69 // an array of RecordHeader because that's not a fundamental type and only |
69 // arrays of fundamental types are allowed. | 70 // arrays of fundamental types are allowed. |
70 RecordHeader* header = | 71 RecordHeader* header = |
71 reinterpret_cast<RecordHeader*>(allocator_->GetAsArray<char>( | 72 reinterpret_cast<RecordHeader*>(allocator_->GetAsArray<char>( |
72 alloc_reference_, kTypeIdSystemProfile, sizeof(RecordHeader))); | 73 alloc_reference_, kTypeIdSystemProfile, sizeof(RecordHeader))); |
73 DCHECK(header); | 74 DCHECK(header); |
74 base::subtle::NoBarrier_Store(&header->as_atomic, 0); | 75 base::subtle::NoBarrier_Store(&header->as_atomic, 0); |
75 } | 76 } |
76 | 77 |
77 // Reset member variables. | 78 // Reset member variables. |
| 79 has_complete_profile_ = false; |
78 alloc_reference_ = 0; | 80 alloc_reference_ = 0; |
79 alloc_size_ = 0; | 81 alloc_size_ = 0; |
80 end_offset_ = 0; | 82 end_offset_ = 0; |
81 } | 83 } |
82 | 84 |
83 bool PersistentSystemProfile::RecordAllocator::Write( | 85 bool PersistentSystemProfile::RecordAllocator::Write( |
84 RecordType type, | 86 RecordType type, |
85 const std::string& record) { | 87 const std::string& record) { |
86 const char* data = record.data(); | 88 const char* data = record.data(); |
87 size_t remaining_size = record.size(); | 89 size_t remaining_size = record.size(); |
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
257 PersistentSystemProfile::~PersistentSystemProfile() {} | 259 PersistentSystemProfile::~PersistentSystemProfile() {} |
258 | 260 |
259 void PersistentSystemProfile::RegisterPersistentAllocator( | 261 void PersistentSystemProfile::RegisterPersistentAllocator( |
260 base::PersistentMemoryAllocator* memory_allocator) { | 262 base::PersistentMemoryAllocator* memory_allocator) { |
261 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); | 263 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
262 | 264 |
263 // Create and store the allocator. A |min_size| of "1" ensures that a memory | 265 // Create and store the allocator. A |min_size| of "1" ensures that a memory |
264 // block is reserved now. | 266 // block is reserved now. |
265 RecordAllocator allocator(memory_allocator, 1); | 267 RecordAllocator allocator(memory_allocator, 1); |
266 allocators_.push_back(std::move(allocator)); | 268 allocators_.push_back(std::move(allocator)); |
| 269 all_have_complete_profile_ = false; |
267 } | 270 } |
268 | 271 |
269 void PersistentSystemProfile::DeregisterPersistentAllocator( | 272 void PersistentSystemProfile::DeregisterPersistentAllocator( |
270 base::PersistentMemoryAllocator* memory_allocator) { | 273 base::PersistentMemoryAllocator* memory_allocator) { |
271 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); | 274 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
272 | 275 |
273 // This would be more efficient with a std::map but it's not expected that | 276 // This would be more efficient with a std::map but it's not expected that |
274 // allocators will get deregistered with any frequency, if at all. | 277 // allocators will get deregistered with any frequency, if at all. |
275 base::EraseIf(allocators_, [=](RecordAllocator& records) { | 278 base::EraseIf(allocators_, [=](RecordAllocator& records) { |
276 return records.allocator() == memory_allocator; | 279 return records.allocator() == memory_allocator; |
277 }); | 280 }); |
278 } | 281 } |
279 | 282 |
280 void PersistentSystemProfile::SetSystemProfile( | 283 void PersistentSystemProfile::SetSystemProfile( |
281 const std::string& serialized_profile) { | 284 const std::string& serialized_profile, |
| 285 bool complete) { |
282 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); | 286 DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); |
283 | 287 |
284 if (allocators_.empty() || serialized_profile.empty()) | 288 if (allocators_.empty() || serialized_profile.empty()) |
285 return; | 289 return; |
286 | 290 |
287 for (auto& allocator : allocators_) { | 291 for (auto& allocator : allocators_) { |
| 292 // Don't overwrite a complete profile with an incomplete one. |
| 293 if (!complete && allocator.has_complete_profile()) |
| 294 continue; |
288 // A full system profile always starts fresh. | 295 // A full system profile always starts fresh. |
289 allocator.Reset(); | 296 allocator.Reset(); |
290 // Write out the serialized profile. | 297 // Write out the serialized profile. |
291 allocator.Write(kSystemProfileProto, serialized_profile); | 298 allocator.Write(kSystemProfileProto, serialized_profile); |
| 299 // Indicate if this is a complete profile. |
| 300 if (complete) |
| 301 allocator.set_complete_profile(); |
292 } | 302 } |
| 303 |
| 304 if (complete) |
| 305 all_have_complete_profile_ = true; |
293 } | 306 } |
294 | 307 |
295 void PersistentSystemProfile::SetSystemProfile( | 308 void PersistentSystemProfile::SetSystemProfile( |
296 const SystemProfileProto& profile) { | 309 const SystemProfileProto& profile, |
| 310 bool complete) { |
| 311 // Avoid serialization if passed profile is not complete and all allocators |
| 312 // already have complete ones. |
| 313 if (!complete && all_have_complete_profile_) |
| 314 return; |
| 315 |
297 std::string serialized_profile; | 316 std::string serialized_profile; |
298 if (!profile.SerializeToString(&serialized_profile)) | 317 if (!profile.SerializeToString(&serialized_profile)) |
299 return; | 318 return; |
300 SetSystemProfile(serialized_profile); | 319 SetSystemProfile(serialized_profile, complete); |
301 } | 320 } |
302 | 321 |
303 // static | 322 // static |
304 bool PersistentSystemProfile::HasSystemProfile( | 323 bool PersistentSystemProfile::HasSystemProfile( |
305 const base::PersistentMemoryAllocator& memory_allocator) { | 324 const base::PersistentMemoryAllocator& memory_allocator) { |
306 const RecordAllocator records(&memory_allocator); | 325 const RecordAllocator records(&memory_allocator); |
307 return records.HasMoreData(); | 326 return records.HasMoreData(); |
308 } | 327 } |
309 | 328 |
310 // static | 329 // static |
(...skipping 12 matching lines...) Expand all Loading... |
323 return system_profile->ParseFromString(record); | 342 return system_profile->ParseFromString(record); |
324 } | 343 } |
325 | 344 |
326 GlobalPersistentSystemProfile* GlobalPersistentSystemProfile::GetInstance() { | 345 GlobalPersistentSystemProfile* GlobalPersistentSystemProfile::GetInstance() { |
327 return base::Singleton< | 346 return base::Singleton< |
328 GlobalPersistentSystemProfile, | 347 GlobalPersistentSystemProfile, |
329 base::LeakySingletonTraits<GlobalPersistentSystemProfile>>::get(); | 348 base::LeakySingletonTraits<GlobalPersistentSystemProfile>>::get(); |
330 } | 349 } |
331 | 350 |
332 } // namespace metrics | 351 } // namespace metrics |
OLD | NEW |