summaryrefslogtreecommitdiffstats
path: root/base/trace_event
diff options
context:
space:
mode:
authorprimiano <primiano@chromium.org>2015-03-19 09:24:38 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-19 16:25:07 +0000
commit13cf4d070f757ce190f49c2ed736518f35ee410b (patch)
tree9684c793629ae76378ca6e2385b01136dbed8a69 /base/trace_event
parentcbcf11d9fa9fd06dd81dd3faf7f69a0e8f54e54f (diff)
downloadchromium_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.gn4
-rw-r--r--base/trace_event/memory_allocator_attributes.h29
-rw-r--r--base/trace_event/memory_allocator_dump.cc91
-rw-r--r--base/trace_event/memory_allocator_dump.h66
-rw-r--r--base/trace_event/memory_allocator_dump_unittest.cc95
-rw-r--r--base/trace_event/memory_dump_manager.cc11
-rw-r--r--base/trace_event/memory_dump_manager.h9
-rw-r--r--base/trace_event/memory_dump_manager_unittest.cc34
-rw-r--r--base/trace_event/memory_dump_provider.cc27
-rw-r--r--base/trace_event/memory_dump_provider.h17
-rw-r--r--base/trace_event/process_memory_dump.cc27
-rw-r--r--base/trace_event/process_memory_dump.h30
-rw-r--r--base/trace_event/process_memory_totals.h2
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;