| 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 |