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.
4
5 #include "third_party/blink/renderer/platform/instrumentation/tracing/web_process_memory_dump.h"
6
7 #include <stddef.h>
8 #include <string>
9
10 #include "base/memory/discardable_memory.h"
11 #include "base/memory/ptr_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/trace_event/process_memory_dump.h"
14 #include "base/trace_event/trace_event_memory_overhead.h"
15 #include "base/trace_event/traced_value.h"
16 #include "skia/ext/skia_trace_memory_dump_impl.h"
17 #include "third_party/blink/renderer/platform/instrumentation/tracing/web_memory_allocator_dump.h"
18 #include "third_party/blink/renderer/platform/wtf/text/string_utf8_adaptor.h"
19
20 namespace blink {
21
WebProcessMemoryDump()22 WebProcessMemoryDump::WebProcessMemoryDump()
23 : owned_process_memory_dump_(new base::trace_event::ProcessMemoryDump(
24 {base::trace_event::MemoryDumpLevelOfDetail::DETAILED})),
25 process_memory_dump_(owned_process_memory_dump_.get()),
26 level_of_detail_(base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {}
27
WebProcessMemoryDump(base::trace_event::MemoryDumpLevelOfDetail level_of_detail,base::trace_event::ProcessMemoryDump * process_memory_dump)28 WebProcessMemoryDump::WebProcessMemoryDump(
29 base::trace_event::MemoryDumpLevelOfDetail level_of_detail,
30 base::trace_event::ProcessMemoryDump* process_memory_dump)
31 : process_memory_dump_(process_memory_dump),
32 level_of_detail_(level_of_detail) {}
33
34 WebProcessMemoryDump::~WebProcessMemoryDump() = default;
35
CreateMemoryAllocatorDump(const String & absolute_name)36 blink::WebMemoryAllocatorDump* WebProcessMemoryDump::CreateMemoryAllocatorDump(
37 const String& absolute_name) {
38 // Get a MemoryAllocatorDump from the base/ object.
39 base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
40 process_memory_dump_->CreateAllocatorDump(absolute_name.Utf8());
41
42 return CreateWebMemoryAllocatorDump(memory_allocator_dump);
43 }
44
CreateMemoryAllocatorDump(const String & absolute_name,blink::WebMemoryAllocatorDumpGuid guid)45 blink::WebMemoryAllocatorDump* WebProcessMemoryDump::CreateMemoryAllocatorDump(
46 const String& absolute_name,
47 blink::WebMemoryAllocatorDumpGuid guid) {
48 // Get a MemoryAllocatorDump from the base/ object with given guid.
49 base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
50 process_memory_dump_->CreateAllocatorDump(
51 absolute_name.Utf8(),
52 base::trace_event::MemoryAllocatorDumpGuid(guid));
53 return CreateWebMemoryAllocatorDump(memory_allocator_dump);
54 }
55
56 blink::WebMemoryAllocatorDump*
CreateWebMemoryAllocatorDump(base::trace_event::MemoryAllocatorDump * memory_allocator_dump)57 WebProcessMemoryDump::CreateWebMemoryAllocatorDump(
58 base::trace_event::MemoryAllocatorDump* memory_allocator_dump) {
59 if (!memory_allocator_dump)
60 return nullptr;
61
62 // Wrap it and return to blink.
63 WebMemoryAllocatorDump* web_memory_allocator_dump =
64 new WebMemoryAllocatorDump(memory_allocator_dump);
65
66 // memory_allocator_dumps_ will take ownership of
67 // |web_memory_allocator_dump|.
68 memory_allocator_dumps_.Set(memory_allocator_dump,
69 base::WrapUnique(web_memory_allocator_dump));
70 return web_memory_allocator_dump;
71 }
72
GetMemoryAllocatorDump(const String & absolute_name) const73 blink::WebMemoryAllocatorDump* WebProcessMemoryDump::GetMemoryAllocatorDump(
74 const String& absolute_name) const {
75 // Retrieve the base MemoryAllocatorDump object and then reverse lookup
76 // its wrapper.
77 base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
78 process_memory_dump_->GetAllocatorDump(absolute_name.Utf8());
79 if (!memory_allocator_dump)
80 return nullptr;
81
82 // The only case of (memory_allocator_dump && !web_memory_allocator_dump)
83 // is something from blink trying to get a MAD that was created from chromium,
84 // which is an odd use case.
85 blink::WebMemoryAllocatorDump* web_memory_allocator_dump =
86 memory_allocator_dumps_.at(memory_allocator_dump);
87 DCHECK(web_memory_allocator_dump);
88 return web_memory_allocator_dump;
89 }
90
Clear()91 void WebProcessMemoryDump::Clear() {
92 // Clear all the WebMemoryAllocatorDump wrappers.
93 memory_allocator_dumps_.clear();
94
95 // Clear the actual MemoryAllocatorDump objects from the underlying PMD.
96 process_memory_dump_->Clear();
97 }
98
TakeAllDumpsFrom(blink::WebProcessMemoryDump * other)99 void WebProcessMemoryDump::TakeAllDumpsFrom(
100 blink::WebProcessMemoryDump* other) {
101 // WebProcessMemoryDump is a container of WebMemoryAllocatorDump(s) which
102 // in turn are wrappers of base::trace_event::MemoryAllocatorDump(s).
103 // In order to expose the move and ownership transfer semantics of the
104 // underlying ProcessMemoryDump, we need to:
105
106 // 1) Move and transfer the ownership of the wrapped
107 // base::trace_event::MemoryAllocatorDump(s) instances.
108 process_memory_dump_->TakeAllDumpsFrom(other->process_memory_dump_);
109
110 // 2) Move and transfer the ownership of the WebMemoryAllocatorDump wrappers.
111 const size_t expected_final_size =
112 memory_allocator_dumps_.size() + other->memory_allocator_dumps_.size();
113 while (!other->memory_allocator_dumps_.IsEmpty()) {
114 auto first_entry = other->memory_allocator_dumps_.begin();
115 base::trace_event::MemoryAllocatorDump* memory_allocator_dump =
116 first_entry->key;
117 memory_allocator_dumps_.Set(
118 memory_allocator_dump,
119 other->memory_allocator_dumps_.Take(memory_allocator_dump));
120 }
121 DCHECK_EQ(expected_final_size, memory_allocator_dumps_.size());
122 DCHECK(other->memory_allocator_dumps_.IsEmpty());
123 }
124
AddOwnershipEdge(blink::WebMemoryAllocatorDumpGuid source,blink::WebMemoryAllocatorDumpGuid target,int importance)125 void WebProcessMemoryDump::AddOwnershipEdge(
126 blink::WebMemoryAllocatorDumpGuid source,
127 blink::WebMemoryAllocatorDumpGuid target,
128 int importance) {
129 process_memory_dump_->AddOwnershipEdge(
130 base::trace_event::MemoryAllocatorDumpGuid(source),
131 base::trace_event::MemoryAllocatorDumpGuid(target), importance);
132 }
133
AddOwnershipEdge(blink::WebMemoryAllocatorDumpGuid source,blink::WebMemoryAllocatorDumpGuid target)134 void WebProcessMemoryDump::AddOwnershipEdge(
135 blink::WebMemoryAllocatorDumpGuid source,
136 blink::WebMemoryAllocatorDumpGuid target) {
137 process_memory_dump_->AddOwnershipEdge(
138 base::trace_event::MemoryAllocatorDumpGuid(source),
139 base::trace_event::MemoryAllocatorDumpGuid(target));
140 }
141
AddSuballocation(blink::WebMemoryAllocatorDumpGuid source,const String & target_node_name)142 void WebProcessMemoryDump::AddSuballocation(
143 blink::WebMemoryAllocatorDumpGuid source,
144 const String& target_node_name) {
145 process_memory_dump_->AddSuballocation(
146 base::trace_event::MemoryAllocatorDumpGuid(source),
147 target_node_name.Utf8());
148 }
149
CreateDumpAdapterForSkia(const String & dump_name_prefix)150 SkTraceMemoryDump* WebProcessMemoryDump::CreateDumpAdapterForSkia(
151 const String& dump_name_prefix) {
152 sk_trace_dump_list_.push_back(std::make_unique<skia::SkiaTraceMemoryDumpImpl>(
153 dump_name_prefix.Utf8(), level_of_detail_, process_memory_dump_));
154 return sk_trace_dump_list_.back().get();
155 }
156
157 blink::WebMemoryAllocatorDump*
CreateDiscardableMemoryAllocatorDump(const std::string & name,base::DiscardableMemory * discardable)158 WebProcessMemoryDump::CreateDiscardableMemoryAllocatorDump(
159 const std::string& name,
160 base::DiscardableMemory* discardable) {
161 base::trace_event::MemoryAllocatorDump* dump =
162 discardable->CreateMemoryAllocatorDump(name.c_str(),
163 process_memory_dump_);
164 return CreateWebMemoryAllocatorDump(dump);
165 }
166
DumpHeapUsage(const std::unordered_map<base::trace_event::AllocationContext,base::trace_event::AllocationMetrics> & metrics_by_context,base::trace_event::TraceEventMemoryOverhead & overhead,const char * allocator_name)167 void WebProcessMemoryDump::DumpHeapUsage(
168 const std::unordered_map<base::trace_event::AllocationContext,
169 base::trace_event::AllocationMetrics>&
170 metrics_by_context,
171 base::trace_event::TraceEventMemoryOverhead& overhead,
172 const char* allocator_name) {
173 process_memory_dump_->DumpHeapUsage(metrics_by_context, overhead,
174 allocator_name);
175 }
176
177 } // namespace content
178