blob: 99f0240a8be4e9dd62d14d7a8fd340606d587d88 [file] [log] [blame]
primianof5999252015-06-11 09:43:15 +09001// 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.
4
5#include "base/trace_event/trace_event_memory_overhead.h"
6
7#include <algorithm>
8
primiano47c69062015-07-25 05:13:32 +09009#include "base/bits.h"
primianof5999252015-06-11 09:43:15 +090010#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"
15
primianof5999252015-06-11 09:43:15 +090016namespace base {
17namespace trace_event {
18
19TraceEventMemoryOverhead::TraceEventMemoryOverhead() {
20}
21
22TraceEventMemoryOverhead::~TraceEventMemoryOverhead() {
23}
24
primianofb2bebf2015-06-13 05:38:20 +090025void TraceEventMemoryOverhead::AddOrCreateInternal(
26 const char* object_type,
27 size_t count,
28 size_t allocated_size_in_bytes,
29 size_t resident_size_in_bytes) {
primianof5999252015-06-11 09:43:15 +090030 auto it = allocated_objects_.find(object_type);
31 if (it == allocated_objects_.end()) {
32 allocated_objects_.insert(std::make_pair(
primianofb2bebf2015-06-13 05:38:20 +090033 object_type,
34 ObjectCountAndSize(
35 {count, allocated_size_in_bytes, resident_size_in_bytes})));
primianof5999252015-06-11 09:43:15 +090036 return;
37 }
38 it->second.count += count;
primianofb2bebf2015-06-13 05:38:20 +090039 it->second.allocated_size_in_bytes += allocated_size_in_bytes;
40 it->second.resident_size_in_bytes += resident_size_in_bytes;
primianof5999252015-06-11 09:43:15 +090041}
42
43void TraceEventMemoryOverhead::Add(const char* object_type,
primianofb2bebf2015-06-13 05:38:20 +090044 size_t allocated_size_in_bytes) {
45 Add(object_type, allocated_size_in_bytes, allocated_size_in_bytes);
46}
47
48void 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);
primianof5999252015-06-11 09:43:15 +090053}
54
55void 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.
primiano47c69062015-07-25 05:13:32 +090059 // - 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));
primianof5999252015-06-11 09:43:15 +090062}
63
64void TraceEventMemoryOverhead::AddRefCountedString(
65 const RefCountedString& str) {
66 Add("RefCountedString", sizeof(RefCountedString));
67 AddString(str.data());
68}
69
70void TraceEventMemoryOverhead::AddValue(const Value& value) {
71 switch (value.GetType()) {
jdoerrie89ee31a2016-12-08 00:43:28 +090072 case Value::Type::NONE:
73 case Value::Type::BOOLEAN:
74 case Value::Type::INTEGER:
75 case Value::Type::DOUBLE:
primianof5999252015-06-11 09:43:15 +090076 Add("FundamentalValue", sizeof(Value));
77 break;
78
jdoerrie89ee31a2016-12-08 00:43:28 +090079 case Value::Type::STRING: {
jdoerrie0d1295b2017-03-06 20:12:04 +090080 const Value* string_value = nullptr;
primianof5999252015-06-11 09:43:15 +090081 value.GetAsString(&string_value);
jdoerrie0d1295b2017-03-06 20:12:04 +090082 Add("StringValue", sizeof(Value));
primianof5999252015-06-11 09:43:15 +090083 AddString(string_value->GetString());
84 } break;
85
jdoerrie89ee31a2016-12-08 00:43:28 +090086 case Value::Type::BINARY: {
jdoerriec56cc7f2017-04-11 16:45:50 +090087 const Value* binary_value = nullptr;
primianof5999252015-06-11 09:43:15 +090088 value.GetAsBinary(&binary_value);
jdoerriec56cc7f2017-04-11 16:45:50 +090089 Add("BinaryValue", sizeof(Value) + binary_value->GetSize());
primianof5999252015-06-11 09:43:15 +090090 } break;
91
jdoerrie89ee31a2016-12-08 00:43:28 +090092 case Value::Type::DICTIONARY: {
primianof5999252015-06-11 09:43:15 +090093 const DictionaryValue* dictionary_value = nullptr;
94 value.GetAsDictionary(&dictionary_value);
95 Add("DictionaryValue", sizeof(DictionaryValue));
96 for (DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd();
97 it.Advance()) {
98 AddString(it.key());
99 AddValue(it.value());
100 }
101 } break;
102
jdoerrie89ee31a2016-12-08 00:43:28 +0900103 case Value::Type::LIST: {
primianof5999252015-06-11 09:43:15 +0900104 const ListValue* list_value = nullptr;
105 value.GetAsList(&list_value);
106 Add("ListValue", sizeof(ListValue));
dcheng1fa44fb2016-05-26 03:30:47 +0900107 for (const auto& v : *list_value)
jdoerrie0143ef02017-04-11 23:20:20 +0900108 AddValue(v);
primianof5999252015-06-11 09:43:15 +0900109 } break;
110
111 default:
112 NOTREACHED();
113 }
114}
115
116void TraceEventMemoryOverhead::AddSelf() {
primianof5999252015-06-11 09:43:15 +0900117 size_t estimated_size = sizeof(*this);
primianofb2bebf2015-06-13 05:38:20 +0900118 // 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();
primianof5999252015-06-11 09:43:15 +0900122 Add("TraceEventMemoryOverhead", estimated_size);
123}
124
oysteined49670a2015-08-07 03:41:47 +0900125size_t TraceEventMemoryOverhead::GetCount(const char* object_type) const {
126 const auto& it = allocated_objects_.find(object_type);
127 if (it == allocated_objects_.end())
128 return 0u;
129 return it->second.count;
130}
131
primianof5999252015-06-11 09:43:15 +0900132void TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead& other) {
133 for (const auto& it : other.allocated_objects_) {
primianofb2bebf2015-06-13 05:38:20 +0900134 AddOrCreateInternal(it.first, it.second.count,
135 it.second.allocated_size_in_bytes,
136 it.second.resident_size_in_bytes);
primianof5999252015-06-11 09:43:15 +0900137 }
138}
139
140void 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,
primianofb2bebf2015-06-13 05:38:20 +0900146 MemoryAllocatorDump::kUnitsBytes,
147 it.second.allocated_size_in_bytes);
148 mad->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes,
149 it.second.resident_size_in_bytes);
bratell38bb9ff2015-09-11 01:28:43 +0900150 mad->AddScalar(MemoryAllocatorDump::kNameObjectCount,
primianof5999252015-06-11 09:43:15 +0900151 MemoryAllocatorDump::kUnitsObjects, it.second.count);
152 }
153}
154
155} // namespace trace_event
156} // namespace base