OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 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 "base/trace_event/memory_allocator_dump.h" | 5 #include "base/trace_event/memory_allocator_dump.h" |
6 | 6 |
7 #include "base/format_macros.h" | 7 #include "base/format_macros.h" |
8 #include "base/strings/stringprintf.h" | 8 #include "base/strings/stringprintf.h" |
9 #include "base/trace_event/memory_allocator_attributes.h" | |
10 #include "base/trace_event/memory_dump_manager.h" | 9 #include "base/trace_event/memory_dump_manager.h" |
11 #include "base/trace_event/memory_dump_provider.h" | 10 #include "base/trace_event/memory_dump_provider.h" |
| 11 #include "base/trace_event/process_memory_dump.h" |
12 #include "base/trace_event/trace_event_argument.h" | 12 #include "base/trace_event/trace_event_argument.h" |
13 #include "base/values.h" | 13 #include "base/values.h" |
14 | 14 |
15 namespace base { | 15 namespace base { |
16 namespace trace_event { | 16 namespace trace_event { |
17 | 17 |
18 MemoryAllocatorDump::MemoryAllocatorDump(const std::string& name, | 18 // static |
19 MemoryAllocatorDump* parent) | 19 const char MemoryAllocatorDump::kRootHeap[] = ""; |
20 : name_(name), | 20 |
21 parent_(parent), | 21 // static |
| 22 std::string MemoryAllocatorDump::GetAbsoluteName( |
| 23 const std::string& allocator_name, |
| 24 const std::string& heap_name) { |
| 25 return allocator_name + (heap_name == kRootHeap ? "" : "/" + heap_name); |
| 26 } |
| 27 |
| 28 MemoryAllocatorDump::MemoryAllocatorDump(const std::string& allocator_name, |
| 29 const std::string& heap_name, |
| 30 ProcessMemoryDump* process_memory_dump) |
| 31 : allocator_name_(allocator_name), |
| 32 heap_name_(heap_name), |
| 33 process_memory_dump_(process_memory_dump), |
22 physical_size_in_bytes_(0), | 34 physical_size_in_bytes_(0), |
23 allocated_objects_count_(0), | 35 allocated_objects_count_(0), |
24 allocated_objects_size_in_bytes_(0) { | 36 allocated_objects_size_in_bytes_(0) { |
25 // Dots are not allowed in the name as the underlying base::DictionaryValue | 37 // The allocator name cannot be empty or contain slash separators. |
| 38 DCHECK(!allocator_name.empty()); |
| 39 DCHECK_EQ(std::string::npos, allocator_name.find_first_of('/')); |
| 40 |
| 41 // The heap_name can be empty and contain slash separator, but not |
| 42 // leading or trailing ones. |
| 43 DCHECK(heap_name.empty() || |
| 44 (heap_name[0] != '/' && *heap_name.rbegin() != '/')); |
| 45 |
| 46 // Dots are not allowed anywhere as the underlying base::DictionaryValue |
26 // would treat them magically and split in sub-nodes, which is not intended. | 47 // would treat them magically and split in sub-nodes, which is not intended. |
27 DCHECK_EQ(std::string::npos, name.find_first_of('.')); | 48 DCHECK_EQ(std::string::npos, allocator_name.find_first_of('.')); |
| 49 DCHECK_EQ(std::string::npos, heap_name.find_first_of('.')); |
28 } | 50 } |
29 | 51 |
30 MemoryAllocatorDump::~MemoryAllocatorDump() { | 52 MemoryAllocatorDump::~MemoryAllocatorDump() { |
31 } | 53 } |
32 | 54 |
33 void MemoryAllocatorDump::SetExtraAttribute(const std::string& name, | 55 void MemoryAllocatorDump::SetAttribute(const std::string& name, int value) { |
34 int value) { | 56 DCHECK(GetAttributesTypeInfo().Exists(allocator_name_, name)) |
35 extra_attributes_.SetInteger(name, value); | 57 << "attribute '" << name << "' not declared." |
| 58 << "See MemoryDumpProvider.DeclareAllocatorAttribute()"; |
| 59 attributes_values_.SetInteger(name, value); |
36 } | 60 } |
37 | 61 |
38 int MemoryAllocatorDump::GetExtraIntegerAttribute( | 62 std::string MemoryAllocatorDump::GetAbsoluteName() const { |
39 const std::string& name) const { | 63 return GetAbsoluteName(allocator_name_, heap_name_); |
40 bool res; | 64 } |
| 65 |
| 66 int MemoryAllocatorDump::GetIntegerAttribute(const std::string& name) const { |
41 int value = -1; | 67 int value = -1; |
42 res = extra_attributes_.GetInteger(name, &value); | 68 bool res = attributes_values_.GetInteger(name, &value); |
43 DCHECK(res) << "Allocator attribute '" << name << "' not found"; | 69 DCHECK(res) << "Attribute '" << name << "' not found"; |
44 return value; | 70 return value; |
45 } | 71 } |
46 | 72 |
47 void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { | 73 void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { |
48 static const char kHexFmt[] = "%" PRIx64; | 74 static const char kHexFmt[] = "%" PRIx64; |
49 | 75 |
50 value->BeginDictionary(name_.c_str()); | 76 value->BeginDictionary(GetAbsoluteName().c_str()); |
51 | |
52 if (parent_) | |
53 value->SetString("parent", parent_->name_); | |
54 | 77 |
55 value->SetString("physical_size_in_bytes", | 78 value->SetString("physical_size_in_bytes", |
56 StringPrintf(kHexFmt, physical_size_in_bytes_)); | 79 StringPrintf(kHexFmt, physical_size_in_bytes_)); |
57 value->SetString("allocated_objects_count", | 80 value->SetString("allocated_objects_count", |
58 StringPrintf(kHexFmt, allocated_objects_count_)); | 81 StringPrintf(kHexFmt, allocated_objects_count_)); |
59 value->SetString("allocated_objects_size_in_bytes", | 82 value->SetString("allocated_objects_size_in_bytes", |
60 StringPrintf(kHexFmt, allocated_objects_size_in_bytes_)); | 83 StringPrintf(kHexFmt, allocated_objects_size_in_bytes_)); |
61 | 84 |
62 // Copy all the extra attributes. | 85 // Copy all the extra attributes. |
63 const MemoryDumpProvider* mdp = | |
64 MemoryDumpManager::GetInstance()->dump_provider_currently_active(); | |
65 const MemoryAllocatorDeclaredAttributes& extra_attributes_types = | |
66 mdp->allocator_attributes(); | |
67 | |
68 value->BeginDictionary("args"); | 86 value->BeginDictionary("args"); |
69 for (DictionaryValue::Iterator it(extra_attributes_); !it.IsAtEnd(); | 87 for (DictionaryValue::Iterator it(attributes_values_); !it.IsAtEnd(); |
70 it.Advance()) { | 88 it.Advance()) { |
71 const std::string& attr_name = it.key(); | 89 const std::string& attr_name = it.key(); |
72 const Value& attr_value = it.value(); | 90 const Value& attr_value = it.value(); |
73 value->BeginDictionary(attr_name.c_str()); | 91 value->BeginDictionary(attr_name.c_str()); |
74 value->SetValue("value", attr_value.DeepCopy()); | 92 value->SetValue("value", attr_value.DeepCopy()); |
75 | 93 |
76 auto attr_it = extra_attributes_types.find(attr_name); | |
77 DCHECK(attr_it != extra_attributes_types.end()) | |
78 << "Allocator attribute " << attr_name | |
79 << " not declared for the dumper " << mdp->GetFriendlyName(); | |
80 | |
81 // TODO(primiano): the "type" should be dumped just once, not repeated on | 94 // TODO(primiano): the "type" should be dumped just once, not repeated on |
82 // on every event. The ability of doing so depends on crbug.com/466121. | 95 // on every event. The ability of doing so depends on crbug.com/466121. |
83 value->SetString("type", attr_it->second.type); | 96 const std::string& attr_type = |
| 97 GetAttributesTypeInfo().Get(allocator_name_, attr_name); |
| 98 DCHECK(!attr_type.empty()); |
| 99 value->SetString("type", attr_type); |
84 | 100 |
85 value->EndDictionary(); // "arg_name": { "type": "...", "value": "..." } | 101 value->EndDictionary(); // "arg_name": { "type": "...", "value": "..." } |
86 } | 102 } |
87 value->EndDictionary(); // "args": {} | 103 value->EndDictionary(); // "args": { ... } |
88 | 104 |
89 value->EndDictionary(); // "allocator name": {} | 105 value->EndDictionary(); // "allocator_name/heap_subheap": { ... } |
| 106 } |
| 107 |
| 108 const MemoryAllocatorAttributesTypeInfo& |
| 109 MemoryAllocatorDump::GetAttributesTypeInfo() const { |
| 110 return process_memory_dump_->session_state()->allocators_attributes_type_info; |
90 } | 111 } |
91 | 112 |
92 } // namespace trace_event | 113 } // namespace trace_event |
93 } // namespace base | 114 } // namespace base |
OLD | NEW |