diff options
author | primiano <primiano@chromium.org> | 2015-03-19 09:24:38 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-03-19 16:25:07 +0000 |
commit | 13cf4d070f757ce190f49c2ed736518f35ee410b (patch) | |
tree | 9684c793629ae76378ca6e2385b01136dbed8a69 /base/trace_event | |
parent | cbcf11d9fa9fd06dd81dd3faf7f69a0e8f54e54f (diff) | |
download | chromium_src-13cf4d070f757ce190f49c2ed736518f35ee410b.zip chromium_src-13cf4d070f757ce190f49c2ed736518f35ee410b.tar.gz chromium_src-13cf4d070f757ce190f49c2ed736518f35ee410b.tar.bz2 |
[tracing] Introduce support for userland memory allocators dumps.
This introduces the MemoryAllocatorDump which defines the ground data
model that every allocator MemoryDumpProvider must comply with in order
to get a coherent snapshot of the various allocators inside the trace.
Furthermore, MemoryDumpProvider(s) can specify further attributes that
will be attached to each dump point using the MemoryAllocatorAttributes
map.
BUG=466141
Review URL: https://codereview.chromium.org/987043003
Cr-Commit-Position: refs/heads/master@{#321368}
Diffstat (limited to 'base/trace_event')
-rw-r--r-- | base/trace_event/BUILD.gn | 4 | ||||
-rw-r--r-- | base/trace_event/memory_allocator_attributes.h | 29 | ||||
-rw-r--r-- | base/trace_event/memory_allocator_dump.cc | 91 | ||||
-rw-r--r-- | base/trace_event/memory_allocator_dump.h | 66 | ||||
-rw-r--r-- | base/trace_event/memory_allocator_dump_unittest.cc | 95 | ||||
-rw-r--r-- | base/trace_event/memory_dump_manager.cc | 11 | ||||
-rw-r--r-- | base/trace_event/memory_dump_manager.h | 9 | ||||
-rw-r--r-- | base/trace_event/memory_dump_manager_unittest.cc | 34 | ||||
-rw-r--r-- | base/trace_event/memory_dump_provider.cc | 27 | ||||
-rw-r--r-- | base/trace_event/memory_dump_provider.h | 17 | ||||
-rw-r--r-- | base/trace_event/process_memory_dump.cc | 27 | ||||
-rw-r--r-- | base/trace_event/process_memory_dump.h | 30 | ||||
-rw-r--r-- | base/trace_event/process_memory_totals.h | 2 |
13 files changed, 434 insertions, 8 deletions
diff --git a/base/trace_event/BUILD.gn b/base/trace_event/BUILD.gn index 10f7ec9..aec694a 100644 --- a/base/trace_event/BUILD.gn +++ b/base/trace_event/BUILD.gn @@ -4,8 +4,12 @@ source_set("trace_event") { sources = [ + "memory_allocator_attributes.h", + "memory_allocator_dump.cc", + "memory_allocator_dump.h", "memory_dump_manager.cc", "memory_dump_manager.h", + "memory_dump_provider.cc", "memory_dump_provider.h", "process_memory_dump.cc", "process_memory_dump.h", diff --git a/base/trace_event/memory_allocator_attributes.h b/base/trace_event/memory_allocator_attributes.h new file mode 100644 index 0000000..efae9de --- /dev/null +++ b/base/trace_event/memory_allocator_attributes.h @@ -0,0 +1,29 @@ +// Copyright 2015 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. + +#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_ +#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_ + +#include <string> + +#include "base/base_export.h" +#include "base/containers/hash_tables.h" + +namespace base { +namespace trace_event { + +struct BASE_EXPORT MemoryAllocatorDeclaredAttribute { + std::string name; + + // Refer to src/tools/perf/unit-info.json for the semantic of the type. + std::string type; +}; + +using MemoryAllocatorDeclaredAttributes = + hash_map<std::string, MemoryAllocatorDeclaredAttribute>; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_ATTRIBUTES_H_ diff --git a/base/trace_event/memory_allocator_dump.cc b/base/trace_event/memory_allocator_dump.cc new file mode 100644 index 0000000..604af7a --- /dev/null +++ b/base/trace_event/memory_allocator_dump.cc @@ -0,0 +1,91 @@ +// Copyright 2015 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/trace_event/memory_allocator_dump.h" + +#include "base/format_macros.h" +#include "base/strings/stringprintf.h" +#include "base/trace_event/memory_allocator_attributes.h" +#include "base/trace_event/memory_dump_manager.h" +#include "base/trace_event/memory_dump_provider.h" +#include "base/trace_event/trace_event_argument.h" +#include "base/values.h" + +namespace base { +namespace trace_event { + +MemoryAllocatorDump::MemoryAllocatorDump(const std::string& name, + MemoryAllocatorDump* parent) + : name_(name), + parent_(parent), + physical_size_in_bytes_(0), + allocated_objects_count_(0), + allocated_objects_size_in_bytes_(0) { + // Dots are not allowed in the name as the underlying base::DictionaryValue + // would treat them magically and split in sub-nodes, which is not intended. + DCHECK_EQ(std::string::npos, name.find_first_of('.')); +} + +MemoryAllocatorDump::~MemoryAllocatorDump() { +} + +void MemoryAllocatorDump::SetExtraAttribute(const std::string& name, + int value) { + extra_attributes_.SetInteger(name, value); +} + +int MemoryAllocatorDump::GetExtraIntegerAttribute( + const std::string& name) const { + bool res; + int value = -1; + res = extra_attributes_.GetInteger(name, &value); + DCHECK(res) << "Allocator attribute '" << name << "' not found"; + return value; +} + +void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { + static const char kHexFmt[] = "%" PRIx64; + + value->BeginDictionary(name_.c_str()); + + value->SetString("parent", parent_ ? parent_->name_ : ""); + value->SetString("physical_size_in_bytes", + StringPrintf(kHexFmt, physical_size_in_bytes_)); + value->SetString("allocated_objects_count", + StringPrintf(kHexFmt, allocated_objects_count_)); + value->SetString("allocated_objects_size_in_bytes", + StringPrintf(kHexFmt, allocated_objects_size_in_bytes_)); + + // Copy all the extra attributes. + const MemoryDumpProvider* mdp = + MemoryDumpManager::GetInstance()->dump_provider_currently_active(); + const MemoryAllocatorDeclaredAttributes& extra_attributes_types = + mdp->allocator_attributes(); + + value->BeginDictionary("args"); + for (DictionaryValue::Iterator it(extra_attributes_); !it.IsAtEnd(); + it.Advance()) { + const std::string& attr_name = it.key(); + const Value& attr_value = it.value(); + value->BeginDictionary(attr_name.c_str()); + value->SetValue("value", attr_value.DeepCopy()); + + auto attr_it = extra_attributes_types.find(attr_name); + DCHECK(attr_it != extra_attributes_types.end()) + << "Allocator attribute " << attr_name + << " not declared for the dumper " << mdp->GetFriendlyName(); + + // TODO(primiano): the "type" should be dumped just once, not repeated on + // on every event. The ability of doing so depends on crbug.com/466121. + value->SetString("type", attr_it->second.type); + + value->EndDictionary(); // "arg_name": { "type": "...", "value": "..." } + } + value->EndDictionary(); // "args": {} + + value->EndDictionary(); // "allocator name": {} +} + +} // namespace trace_event +} // namespace base diff --git a/base/trace_event/memory_allocator_dump.h b/base/trace_event/memory_allocator_dump.h new file mode 100644 index 0000000..4d7293e --- /dev/null +++ b/base/trace_event/memory_allocator_dump.h @@ -0,0 +1,66 @@ +// Copyright 2015 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. + +#ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ +#define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ + +#include "base/base_export.h" +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/trace_event/memory_allocator_attributes.h" +#include "base/values.h" + +namespace base { +namespace trace_event { + +class MemoryDumpManager; +class TracedValue; + +// Data model for user-land memory allocator dumps. +class BASE_EXPORT MemoryAllocatorDump { + public: + MemoryAllocatorDump(const std::string& name, MemoryAllocatorDump* parent); + ~MemoryAllocatorDump(); + + const std::string& name() const { return name_; } + const MemoryAllocatorDump* parent() const { return parent_; } + + void set_physical_size_in_bytes(uint64 value) { + physical_size_in_bytes_ = value; + } + uint64 physical_size_in_bytes() const { return physical_size_in_bytes_; } + + void set_allocated_objects_count(uint64 value) { + allocated_objects_count_ = value; + } + uint64 allocated_objects_count() const { return allocated_objects_count_; } + + void set_allocated_objects_size_in_bytes(uint64 value) { + allocated_objects_size_in_bytes_ = value; + } + uint64 allocated_objects_size_in_bytes() const { + return allocated_objects_size_in_bytes_; + } + + void SetExtraAttribute(const std::string& name, int value); + int GetExtraIntegerAttribute(const std::string& name) const; + + // Called at trace generation time to populate the TracedValue. + void AsValueInto(TracedValue* value) const; + + private: + const std::string name_; + MemoryAllocatorDump* const parent_; // Not owned. + uint64 physical_size_in_bytes_; + uint64 allocated_objects_count_; + uint64 allocated_objects_size_in_bytes_; + DictionaryValue extra_attributes_; + + DISALLOW_COPY_AND_ASSIGN(MemoryAllocatorDump); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ diff --git a/base/trace_event/memory_allocator_dump_unittest.cc b/base/trace_event/memory_allocator_dump_unittest.cc new file mode 100644 index 0000000..8c14560 --- /dev/null +++ b/base/trace_event/memory_allocator_dump_unittest.cc @@ -0,0 +1,95 @@ +// Copyright 2015 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/trace_event/memory_allocator_dump.h" + +#include "base/trace_event/memory_dump_provider.h" +#include "base/trace_event/process_memory_dump.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace trace_event { + +namespace { +class FakeMemoryAllocatorDumpProvider : public MemoryDumpProvider { + public: + FakeMemoryAllocatorDumpProvider() { + DeclareAllocatorAttribute({"attr1", "count"}); + DeclareAllocatorAttribute({"attr2", "bytes"}); + } + + bool DumpInto(ProcessMemoryDump* pmd) override { + MemoryAllocatorDump* mad_foo = pmd->CreateAllocatorDump("foo"); + mad_foo->set_physical_size_in_bytes(4096); + mad_foo->set_allocated_objects_count(42); + mad_foo->set_allocated_objects_size_in_bytes(1000); + mad_foo->SetExtraAttribute("attr1", 1234); + mad_foo->SetExtraAttribute("attr2", 99); + + MemoryAllocatorDump* mad_bar = pmd->CreateAllocatorDump("foo/bar", mad_foo); + mad_bar->set_physical_size_in_bytes(1); + mad_bar->set_allocated_objects_count(2); + mad_bar->set_allocated_objects_size_in_bytes(3); + + pmd->CreateAllocatorDump("baz"); + // Leave the rest of |baz| deliberately uninitialized, to check that + // CreateAllocatorDump returns a properly zero-initialized object. + + return true; + } + + const char* GetFriendlyName() const override { return "mock_allocator"; } +}; +} // namespace + +TEST(MemoryAllocatorDumpTest, DumpIntoProcessMemoryDump) { + FakeMemoryAllocatorDumpProvider fmadp; + ProcessMemoryDump pmd; + + fmadp.DumpInto(&pmd); + + ASSERT_EQ(3u, pmd.allocator_dumps().size()); + + const MemoryAllocatorDump* mad_foo = pmd.GetAllocatorDump("foo"); + ASSERT_NE(nullptr, mad_foo); + EXPECT_EQ("foo", mad_foo->name()); + ASSERT_EQ(nullptr, mad_foo->parent()); + EXPECT_EQ(4096u, mad_foo->physical_size_in_bytes()); + EXPECT_EQ(42u, mad_foo->allocated_objects_count()); + EXPECT_EQ(1000u, mad_foo->allocated_objects_size_in_bytes()); + + // Check the extra attributes of |mad_foo|. + EXPECT_EQ(1234, mad_foo->GetExtraIntegerAttribute("attr1")); + EXPECT_EQ(99, mad_foo->GetExtraIntegerAttribute("attr2")); + + const MemoryAllocatorDump* mad_bar = pmd.GetAllocatorDump("foo/bar"); + ASSERT_NE(nullptr, mad_bar); + EXPECT_EQ("foo/bar", mad_bar->name()); + ASSERT_EQ(mad_foo, mad_bar->parent()); + EXPECT_EQ(1u, mad_bar->physical_size_in_bytes()); + EXPECT_EQ(2u, mad_bar->allocated_objects_count()); + EXPECT_EQ(3u, mad_bar->allocated_objects_size_in_bytes()); + + const MemoryAllocatorDump* mad_baz = pmd.GetAllocatorDump("baz"); + ASSERT_NE(nullptr, mad_baz); + EXPECT_EQ("baz", mad_baz->name()); + ASSERT_EQ(nullptr, mad_baz->parent()); + EXPECT_EQ(0u, mad_baz->physical_size_in_bytes()); + EXPECT_EQ(0u, mad_baz->allocated_objects_count()); + EXPECT_EQ(0u, mad_baz->allocated_objects_size_in_bytes()); +} + +// DEATH tests are not supported in Android / iOS. +#if !defined(NDEBUG) && !defined(OS_ANDROID) && !defined(OS_IOS) +TEST(MemoryAllocatorDumpTest, ForbidDuplicatesDeathTest) { + FakeMemoryAllocatorDumpProvider fmadp; + ProcessMemoryDump pmd; + pmd.CreateAllocatorDump("dump_1"); + pmd.CreateAllocatorDump("dump_2"); + ASSERT_DEATH(pmd.CreateAllocatorDump("dump_1"), ""); +} +#endif + +} // namespace trace_event +} // namespace base diff --git a/base/trace_event/memory_dump_manager.cc b/base/trace_event/memory_dump_manager.cc index 8b2d930..0ec5d19 100644 --- a/base/trace_event/memory_dump_manager.cc +++ b/base/trace_event/memory_dump_manager.cc @@ -59,7 +59,8 @@ void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { g_instance_for_testing = instance; } -MemoryDumpManager::MemoryDumpManager() : memory_tracing_enabled_(0) { +MemoryDumpManager::MemoryDumpManager() + : dump_provider_currently_active_(nullptr), memory_tracing_enabled_(0) { } MemoryDumpManager::~MemoryDumpManager() { @@ -128,17 +129,19 @@ void MemoryDumpManager::CreateLocalDumpPoint(DumpPointType dump_point_type, AutoLock lock(lock_); for (auto it = dump_providers_enabled_.begin(); it != dump_providers_enabled_.end();) { - MemoryDumpProvider* dump_provider = *it; - if (dump_provider->DumpInto(pmd.get())) { + dump_provider_currently_active_ = *it; + if (dump_provider_currently_active_->DumpInto(pmd.get())) { did_any_provider_dump = true; ++it; } else { - LOG(ERROR) << "The memory dumper " << dump_provider->GetFriendlyName() + LOG(ERROR) << "The memory dumper " + << dump_provider_currently_active_->GetFriendlyName() << " failed, possibly due to sandboxing (crbug.com/461788), " "disabling it for current process. Try restarting chrome " "with the --no-sandbox switch."; it = dump_providers_enabled_.erase(it); } + dump_provider_currently_active_ = nullptr; } } diff --git a/base/trace_event/memory_dump_manager.h b/base/trace_event/memory_dump_manager.h index 8a9b3b7..04d0135 100644 --- a/base/trace_event/memory_dump_manager.h +++ b/base/trace_event/memory_dump_manager.h @@ -49,6 +49,12 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { void OnTraceLogEnabled() override; void OnTraceLogDisabled() override; + // Returns the MemoryDumpProvider which is currently being dumping into a + // ProcessMemoryDump via DumpInto(...) if any, nullptr otherwise. + MemoryDumpProvider* dump_provider_currently_active() const { + return dump_provider_currently_active_; + } + private: friend struct DefaultDeleter<MemoryDumpManager>; // For the testing instance. friend struct DefaultSingletonTraits<MemoryDumpManager>; @@ -70,6 +76,9 @@ class BASE_EXPORT MemoryDumpManager : public TraceLog::EnabledStateObserver { std::vector<MemoryDumpProvider*> dump_providers_registered_; // Not owned. std::vector<MemoryDumpProvider*> dump_providers_enabled_; // Not owned. + // TODO(primiano): this is required only until crbug.com/466121 gets fixed. + MemoryDumpProvider* dump_provider_currently_active_; // Now owned. + // Protects from concurrent accesses to the |dump_providers_*|, e.g., tearing // down logging while creating a dump point on another thread. Lock lock_; diff --git a/base/trace_event/memory_dump_manager_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc index 251a92a..65e719f 100644 --- a/base/trace_event/memory_dump_manager_unittest.cc +++ b/base/trace_event/memory_dump_manager_unittest.cc @@ -10,6 +10,7 @@ #include "testing/gtest/include/gtest/gtest.h" using testing::_; +using testing::Invoke; using testing::Return; namespace base { @@ -51,6 +52,14 @@ class MockDumpProvider : public MemoryDumpProvider { public: MOCK_METHOD1(DumpInto, bool(ProcessMemoryDump* pmd)); + // DumpInto() override for the ActiveDumpProviderConsistency test, + bool DumpIntoAndCheckDumpProviderCurrentlyActive(ProcessMemoryDump* pmd) { + EXPECT_EQ( + this, + MemoryDumpManager::GetInstance()->dump_provider_currently_active()); + return true; + } + const char* GetFriendlyName() const override { return "MockDumpProvider"; } }; @@ -148,5 +157,30 @@ TEST_F(MemoryDumpManagerTest, DisableFailingDumpers) { DisableTracing(); } +// TODO(primiano): remove once crbug.com/466121 gets fixed. +// Ascertains that calls to MDM::dump_provider_currently_active() actually +// returns the MemoryDumpProvider currently active during the DumpInto() call. +TEST_F(MemoryDumpManagerTest, ActiveDumpProviderConsistency) { + MockDumpProvider mdp1; + MockDumpProvider mdp2; + + mdm_->RegisterDumpProvider(&mdp1); + mdm_->RegisterDumpProvider(&mdp2); + EnableTracing(kTraceCategory); + EXPECT_CALL(mdp1, DumpInto(_)) + .Times(2) + .WillRepeatedly(Invoke( + &mdp1, + &MockDumpProvider::DumpIntoAndCheckDumpProviderCurrentlyActive)); + EXPECT_CALL(mdp2, DumpInto(_)) + .Times(2) + .WillRepeatedly(Invoke( + &mdp2, + &MockDumpProvider::DumpIntoAndCheckDumpProviderCurrentlyActive)); + mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED); + mdm_->RequestDumpPoint(DumpPointType::EXPLICITLY_TRIGGERED); + DisableTracing(); +} + } // namespace trace_event } // namespace base diff --git a/base/trace_event/memory_dump_provider.cc b/base/trace_event/memory_dump_provider.cc new file mode 100644 index 0000000..9518461 --- /dev/null +++ b/base/trace_event/memory_dump_provider.cc @@ -0,0 +1,27 @@ +// Copyright 2015 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/trace_event/memory_dump_provider.h" + +#include "base/logging.h" + +namespace base { +namespace trace_event { + +MemoryDumpProvider::MemoryDumpProvider() { +} + +MemoryDumpProvider::~MemoryDumpProvider() { +} + +void MemoryDumpProvider::DeclareAllocatorAttribute( + const MemoryAllocatorDeclaredAttribute& attr) { + DCHECK_EQ(0u, allocator_attributes_.count(attr.name)) + << "Allocator attribute " << attr.name << " already declared for dumper " + << GetFriendlyName(); + allocator_attributes_[attr.name] = attr; +} + +} // namespace trace_event +} // namespace base diff --git a/base/trace_event/memory_dump_provider.h b/base/trace_event/memory_dump_provider.h index 1c5bbb1..5cc3a6e 100644 --- a/base/trace_event/memory_dump_provider.h +++ b/base/trace_event/memory_dump_provider.h @@ -6,7 +6,7 @@ #define BASE_TRACE_EVENT_MEMORY_DUMP_PROVIDER_H_ #include "base/base_export.h" -#include "base/macros.h" +#include "base/trace_event/memory_allocator_attributes.h" namespace base { namespace trace_event { @@ -22,11 +22,22 @@ class BASE_EXPORT MemoryDumpProvider { virtual const char* GetFriendlyName() const = 0; + const MemoryAllocatorDeclaredAttributes& allocator_attributes() const { + return allocator_attributes_; + } + protected: - MemoryDumpProvider() {} - virtual ~MemoryDumpProvider() {} + MemoryDumpProvider(); + virtual ~MemoryDumpProvider(); + + void DeclareAllocatorAttribute(const MemoryAllocatorDeclaredAttribute& attr); private: + // The map (attribute name -> type) that specifies the semantic of the + // extra attributes that the MemoryAllocatorDump(s) produced by this + // MemoryDumpProvider will have. + MemoryAllocatorDeclaredAttributes allocator_attributes_; + DISALLOW_COPY_AND_ASSIGN(MemoryDumpProvider); }; diff --git a/base/trace_event/process_memory_dump.cc b/base/trace_event/process_memory_dump.cc index 5363db55..bbca36c 100644 --- a/base/trace_event/process_memory_dump.cc +++ b/base/trace_event/process_memory_dump.cc @@ -17,6 +17,27 @@ ProcessMemoryDump::ProcessMemoryDump() ProcessMemoryDump::~ProcessMemoryDump() { } +MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( + const std::string& name) { + return CreateAllocatorDump(name, nullptr); +} + +MemoryAllocatorDump* ProcessMemoryDump::CreateAllocatorDump( + const std::string& name, + MemoryAllocatorDump* parent) { + DCHECK_EQ(0ul, allocator_dumps_.count(name)); + MemoryAllocatorDump* mad = new MemoryAllocatorDump(name, parent); + allocator_dumps_storage_.push_back(mad); + allocator_dumps_[name] = mad; + return mad; +} + +MemoryAllocatorDump* ProcessMemoryDump::GetAllocatorDump( + const std::string& name) const { + auto it = allocator_dumps_.find(name); + return it == allocator_dumps_.end() ? nullptr : it->second; +} + void ProcessMemoryDump::AsValueInto(TracedValue* value) const { // Build up the [dumper name] -> [value] dictionary. if (has_process_totals_) { @@ -29,6 +50,12 @@ void ProcessMemoryDump::AsValueInto(TracedValue* value) const { process_mmaps_.AsValueInto(value); value->EndDictionary(); } + if (allocator_dumps_storage_.size() > 0) { + value->BeginDictionary("allocators"); + for (const MemoryAllocatorDump* allocator_dump : allocator_dumps_storage_) + allocator_dump->AsValueInto(value); + value->EndDictionary(); + } } } // namespace trace_event diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h index 4256c4c..df6cc82 100644 --- a/base/trace_event/process_memory_dump.h +++ b/base/trace_event/process_memory_dump.h @@ -6,6 +6,10 @@ #define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ #include "base/base_export.h" +#include "base/containers/hash_tables.h" +#include "base/containers/small_map.h" +#include "base/memory/scoped_vector.h" +#include "base/trace_event/memory_allocator_dump.h" #include "base/trace_event/process_memory_maps.h" #include "base/trace_event/process_memory_totals.h" @@ -13,6 +17,7 @@ namespace base { namespace trace_event { class ConvertableToTraceFormat; +class MemoryDumpManager; // ProcessMemoryDump is as a strongly typed container which enforces the data // model for each memory dump point and holds the dumps produced by the @@ -22,6 +27,9 @@ class ConvertableToTraceFormat; // dump point time. class BASE_EXPORT ProcessMemoryDump { public: + using AllocatorDumpsMap = + SmallMap<hash_map<std::string, MemoryAllocatorDump*>>; + ProcessMemoryDump(); ~ProcessMemoryDump(); @@ -36,6 +44,21 @@ class BASE_EXPORT ProcessMemoryDump { bool has_process_mmaps() const { return has_process_mmaps_; } void set_has_process_mmaps() { has_process_mmaps_ = true; } + // Creates a new MemoryAllocatorDump with the given name and returns the + // empty object back to the caller. The |name| must be unique in the dump. + // ProcessMemoryDump handles the memory ownership of the created object. + // |parent| can be used to specify a hierarchical relationship of the + // allocator dumps. + MemoryAllocatorDump* CreateAllocatorDump(const std::string& name); + MemoryAllocatorDump* CreateAllocatorDump(const std::string& name, + MemoryAllocatorDump* parent); + + // Returns a MemoryAllocatorDump given its name or nullptr if not found. + MemoryAllocatorDump* GetAllocatorDump(const std::string& name) const; + + // Returns the map of the MemoryAllocatorDumps added to this dump. + const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; } + private: ProcessMemoryTotals process_totals_; bool has_process_totals_; @@ -43,6 +66,13 @@ class BASE_EXPORT ProcessMemoryDump { ProcessMemoryMaps process_mmaps_; bool has_process_mmaps_; + // A maps of "allocator_name" -> MemoryAllocatorDump populated by + // allocator dump providers. + AllocatorDumpsMap allocator_dumps_; + + // ProcessMemoryDump handles the memory ownership of all its belongings. + ScopedVector<MemoryAllocatorDump> allocator_dumps_storage_; + DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump); }; diff --git a/base/trace_event/process_memory_totals.h b/base/trace_event/process_memory_totals.h index 1c99152..ef0289e 100644 --- a/base/trace_event/process_memory_totals.h +++ b/base/trace_event/process_memory_totals.h @@ -16,7 +16,7 @@ class TracedValue; // Dump provider which collects process-wide memory stats. class BASE_EXPORT ProcessMemoryTotals { public: - ProcessMemoryTotals() {} + ProcessMemoryTotals() : resident_set_bytes_(0) {} // Called at trace generation time to populate the TracedValue. void AsValueInto(TracedValue* value) const; |