Chromium Code Reviews| Index: base/debug/activity_analyzer.cc |
| diff --git a/base/debug/activity_analyzer.cc b/base/debug/activity_analyzer.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b8a309f95bb5824123180ed4f54efedc7afe374c |
| --- /dev/null |
| +++ b/base/debug/activity_analyzer.cc |
| @@ -0,0 +1,124 @@ |
| +// Copyright 2016 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/debug/activity_analyzer.h" |
| + |
| +#include "base/files/file.h" |
| +#include "base/files/file_path.h" |
| +#include "base/files/memory_mapped_file.h" |
| +#include "base/logging.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "base/stl_util.h" |
| +#include "base/strings/string_util.h" |
| + |
| +namespace base { |
| +namespace debug { |
| + |
| +ThreadActivityAnalyzer::ThreadActivityAnalyzer( |
| + const ThreadActivityTracker* tracker) |
| + : activity_snapshot_valid_(tracker->Snapshot(&activity_snapshot_)) {} |
| + |
| +ThreadActivityAnalyzer::ThreadActivityAnalyzer(void* base, size_t size) |
| + : ThreadActivityAnalyzer( |
| + WrapUnique(new ThreadActivityTracker(base, size)).get()) {} |
| + |
| +ThreadActivityAnalyzer::ThreadActivityAnalyzer( |
| + PersistentMemoryAllocator* allocator, |
| + PersistentMemoryAllocator::Reference reference) |
| + : ThreadActivityAnalyzer(allocator->GetAsObject<char>( |
| + reference, |
| + GlobalActivityTracker::kTypeIdActivityTracker), |
| + allocator->GetAllocSize(reference)) {} |
| + |
| +ThreadActivityAnalyzer::~ThreadActivityAnalyzer() {} |
| + |
| +GlobalActivityAnalyzer::GlobalActivityAnalyzer( |
| + std::unique_ptr<PersistentMemoryAllocator> allocator) |
| + : allocator_(std::move(allocator)), allocator_iterator_(allocator_.get()) {} |
| + |
| +GlobalActivityAnalyzer::~GlobalActivityAnalyzer() {} |
| + |
| +#if !defined(OS_NACL) |
| +std::unique_ptr<GlobalActivityAnalyzer> GlobalActivityAnalyzer::CreateWithFile( |
| + const FilePath& file_path) { |
| + std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); |
| + mmfile->Initialize(file_path); |
| + if (!mmfile->IsValid()) |
| + return nullptr; |
| + |
| + if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) |
| + return nullptr; |
| + |
| + return WrapUnique(new GlobalActivityAnalyzer( |
| + WrapUnique(new FilePersistentMemoryAllocator( |
| + std::move(mmfile), 0, 0, base::StringPiece(), |
| + true)))); |
| +} |
| +#endif // !defined(OS_NACL) |
| + |
| +ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetFirstAnalyzer() { |
| + // Fetch all the records. This will retrieve only ones created since the |
| + // last run since the PMA iterator will continue from where it left off. |
| + uint32_t type; |
|
Sigurður Ásgeirsson
2016/06/14 15:28:12
Maybe tuck most of the body of this function into
bcwhite
2016/06/14 15:54:56
Ummm... I specifically said that the activity_ana
bcwhite
2016/06/14 19:48:45
Done.
|
| + PersistentMemoryAllocator::Reference ref; |
| + while ((ref = allocator_iterator_.GetNext(&type)) != 0) { |
| + switch (type) { |
| + case GlobalActivityTracker::kTypeIdActivityTracker: |
| + case GlobalActivityTracker::kTypeIdActivityTrackerFree: |
| + // Free or not, add it to the list of references for later analysis. |
| + tracker_references_.insert(ref); |
| + break; |
| + } |
| + } |
| + |
| + // Go through all the known references and create analyzers for them with |
| + // snapshots of the current state. |
| + analyzers_.clear(); |
| + for (PersistentMemoryAllocator::Reference tracker_ref : tracker_references_) { |
| + // Get the actual data segment for the tracker. This can fail if the |
| + // record has been marked "free" since the type will not match. |
| + void* base = allocator_->GetAsObject<char>( |
| + tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker); |
| + if (!base) |
| + continue; |
| + |
| + // Create the analyzer on the data. This will capture a snapshot of the |
| + // tracker state. This can fail if the tracker is somehow corrupted or is |
| + // in the process of shutting down. |
| + std::unique_ptr<ThreadActivityAnalyzer> analyzer(new ThreadActivityAnalyzer( |
| + base, allocator_->GetAllocSize(tracker_ref))); |
| + if (!analyzer->IsValid()) |
| + continue; |
| + |
| + // Add this analyzer to the map of known ones, indexed by a unique thread |
| + // identifier. |
| + analyzer->allocator_reference_ = ref; |
| + analyzers_[analyzer->GetThreadKey()] = std::move(analyzer); |
|
Sigurður Ásgeirsson
2016/06/14 15:28:12
not having read the analyzer code, it's not clear
bcwhite
2016/06/14 19:48:45
Only active (currently executing) trackers are inc
|
| + } |
| + |
| + // Set up the iterator for going through all the analyzers. |
| + analyzers_iterator_ = analyzers_.begin(); |
| + if (analyzers_iterator_ == analyzers_.end()) |
| + return nullptr; |
| + return analyzers_iterator_->second.get(); |
| +} |
| + |
| +ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetNextAnalyzer() { |
| + DCHECK(analyzers_iterator_ != analyzers_.end()); |
| + ++analyzers_iterator_; |
| + if (analyzers_iterator_ == analyzers_.end()) |
| + return nullptr; |
| + return analyzers_iterator_->second.get(); |
| +} |
| + |
| +ThreadActivityAnalyzer* GlobalActivityAnalyzer::GetAnalyzerForThread( |
| + const ThreadKey& key) { |
| + auto found = analyzers_.find(key); |
| + if (found == analyzers_.end()) |
| + return nullptr; |
| + return found->second.get(); |
| +} |
| + |
| +} // namespace debug |
| +} // namespace base |