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
3 // found in the LICENSE file.
5 #include "base/trace_event/trace_event_memory_overhead.h"
10 #include "base/memory/ref_counted_memory.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/trace_event/memory_allocator_dump.h"
13 #include "base/trace_event/process_memory_dump.h"
14 #include "base/values.h"
17 namespace trace_event
{
19 TraceEventMemoryOverhead::TraceEventMemoryOverhead() {
22 TraceEventMemoryOverhead::~TraceEventMemoryOverhead() {
25 void TraceEventMemoryOverhead::AddOrCreateInternal(
26 const char* object_type
,
28 size_t allocated_size_in_bytes
,
29 size_t resident_size_in_bytes
) {
30 auto it
= allocated_objects_
.find(object_type
);
31 if (it
== allocated_objects_
.end()) {
32 allocated_objects_
.insert(std::make_pair(
35 {count
, allocated_size_in_bytes
, resident_size_in_bytes
})));
38 it
->second
.count
+= count
;
39 it
->second
.allocated_size_in_bytes
+= allocated_size_in_bytes
;
40 it
->second
.resident_size_in_bytes
+= resident_size_in_bytes
;
43 void TraceEventMemoryOverhead::Add(const char* object_type
,
44 size_t allocated_size_in_bytes
) {
45 Add(object_type
, allocated_size_in_bytes
, allocated_size_in_bytes
);
48 void TraceEventMemoryOverhead::Add(const char* object_type
,
49 size_t allocated_size_in_bytes
,
50 size_t resident_size_in_bytes
) {
51 AddOrCreateInternal(object_type
, 1, allocated_size_in_bytes
,
52 resident_size_in_bytes
);
55 void TraceEventMemoryOverhead::AddString(const std::string
& str
) {
56 // The number below are empirical and mainly based on profiling of real-world
57 // std::string implementations:
58 // - even short string end up malloc()-inc at least 32 bytes.
59 // - longer strings seem to malloc() multiples of 16 bytes.
60 const size_t capacity
= bits::Align(str
.capacity(), 16);
61 Add("std::string", sizeof(std::string
) + std::max
<size_t>(capacity
, 32u));
64 void TraceEventMemoryOverhead::AddRefCountedString(
65 const RefCountedString
& str
) {
66 Add("RefCountedString", sizeof(RefCountedString
));
67 AddString(str
.data());
70 void TraceEventMemoryOverhead::AddValue(const Value
& value
) {
71 switch (value
.GetType()) {
72 case Value::TYPE_NULL
:
73 case Value::TYPE_BOOLEAN
:
74 case Value::TYPE_INTEGER
:
75 case Value::TYPE_DOUBLE
:
76 Add("FundamentalValue", sizeof(Value
));
79 case Value::TYPE_STRING
: {
80 const StringValue
* string_value
= nullptr;
81 value
.GetAsString(&string_value
);
82 Add("StringValue", sizeof(StringValue
));
83 AddString(string_value
->GetString());
86 case Value::TYPE_BINARY
: {
87 const BinaryValue
* binary_value
= nullptr;
88 value
.GetAsBinary(&binary_value
);
89 Add("BinaryValue", sizeof(BinaryValue
) + binary_value
->GetSize());
92 case Value::TYPE_DICTIONARY
: {
93 const DictionaryValue
* dictionary_value
= nullptr;
94 value
.GetAsDictionary(&dictionary_value
);
95 Add("DictionaryValue", sizeof(DictionaryValue
));
96 for (DictionaryValue::Iterator
it(*dictionary_value
); !it
.IsAtEnd();
103 case Value::TYPE_LIST
: {
104 const ListValue
* list_value
= nullptr;
105 value
.GetAsList(&list_value
);
106 Add("ListValue", sizeof(ListValue
));
107 for (const Value
* v
: *list_value
)
116 void TraceEventMemoryOverhead::AddSelf() {
117 size_t estimated_size
= sizeof(*this);
118 // If the SmallMap did overflow its static capacity, its elements will be
119 // allocated on the heap and have to be accounted separately.
120 if (allocated_objects_
.UsingFullMap())
121 estimated_size
+= sizeof(map_type::value_type
) * allocated_objects_
.size();
122 Add("TraceEventMemoryOverhead", estimated_size
);
125 size_t TraceEventMemoryOverhead::GetCount(const char* object_type
) const {
126 const auto& it
= allocated_objects_
.find(object_type
);
127 if (it
== allocated_objects_
.end())
129 return it
->second
.count
;
132 void TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead
& other
) {
133 for (const auto& it
: other
.allocated_objects_
) {
134 AddOrCreateInternal(it
.first
, it
.second
.count
,
135 it
.second
.allocated_size_in_bytes
,
136 it
.second
.resident_size_in_bytes
);
140 void TraceEventMemoryOverhead::DumpInto(const char* base_name
,
141 ProcessMemoryDump
* pmd
) const {
142 for (const auto& it
: allocated_objects_
) {
143 std::string dump_name
= StringPrintf("%s/%s", base_name
, it
.first
);
144 MemoryAllocatorDump
* mad
= pmd
->CreateAllocatorDump(dump_name
);
145 mad
->AddScalar(MemoryAllocatorDump::kNameSize
,
146 MemoryAllocatorDump::kUnitsBytes
,
147 it
.second
.allocated_size_in_bytes
);
148 mad
->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes
,
149 it
.second
.resident_size_in_bytes
);
150 mad
->AddScalar(MemoryAllocatorDump::kNameObjectCount
,
151 MemoryAllocatorDump::kUnitsObjects
, it
.second
.count
);
155 } // namespace trace_event