Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(382)

Side by Side Diff: services/resource_coordinator/memory/coordinator/coordinator_impl.cc

Issue 2883693002: [Memory-UMA] Implement basic working prototype. (Closed)
Patch Set: Fix test. Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "services/resource_coordinator/memory/coordinator/coordinator_impl.h" 5 #include "services/resource_coordinator/memory/coordinator/coordinator_impl.h"
6 6
7 #include <utility>
8
7 #include "base/bind.h" 9 #include "base/bind.h"
8 #include "base/bind_helpers.h" 10 #include "base/bind_helpers.h"
9 #include "base/location.h" 11 #include "base/location.h"
10 #include "base/logging.h" 12 #include "base/logging.h"
11 #include "base/memory/ref_counted.h" 13 #include "base/memory/ref_counted.h"
12 #include "base/single_thread_task_runner.h" 14 #include "base/single_thread_task_runner.h"
13 #include "base/threading/platform_thread.h" 15 #include "base/threading/platform_thread.h"
14 #include "base/trace_event/memory_dump_manager.h" 16 #include "base/trace_event/memory_dump_manager.h"
15 #include "base/trace_event/memory_dump_request_args.h" 17 #include "base/trace_event/memory_dump_request_args.h"
16 #include "services/resource_coordinator/public/cpp/memory/process_local_dump_man ager_impl.h" 18 #include "services/resource_coordinator/public/cpp/memory/process_local_dump_man ager_impl.h"
17 #include "services/resource_coordinator/public/interfaces/memory/constants.mojom .h" 19 #include "services/resource_coordinator/public/interfaces/memory/constants.mojom .h"
18 #include "services/resource_coordinator/public/interfaces/memory/memory_instrume ntation.mojom.h" 20 #include "services/resource_coordinator/public/interfaces/memory/memory_instrume ntation.mojom.h"
21 #include "services/service_manager/public/cpp/identity.h"
22 #include "services/service_manager/public/interfaces/service_manager.mojom.h"
19 23
20 #if defined(OS_MACOSX) && !defined(OS_IOS) 24 #if defined(OS_MACOSX) && !defined(OS_IOS)
21 #include "base/mac/mac_util.h" 25 #include "base/mac/mac_util.h"
22 #endif 26 #endif
23 27
24 namespace { 28 namespace {
25 29
26 memory_instrumentation::CoordinatorImpl* g_coordinator_impl; 30 memory_instrumentation::CoordinatorImpl* g_coordinator_impl;
27 31
28 uint32_t CalculatePrivateFootprintKb( 32 uint32_t CalculatePrivateFootprintKb(
(...skipping 22 matching lines...) Expand all
51 55
52 } // namespace 56 } // namespace
53 57
54 namespace memory_instrumentation { 58 namespace memory_instrumentation {
55 59
56 // static 60 // static
57 CoordinatorImpl* CoordinatorImpl::GetInstance() { 61 CoordinatorImpl* CoordinatorImpl::GetInstance() {
58 return g_coordinator_impl; 62 return g_coordinator_impl;
59 } 63 }
60 64
61 CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager) 65 CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager,
66 service_manager::Connector* connector)
62 : failed_memory_dump_count_(0), 67 : failed_memory_dump_count_(0),
63 initialize_memory_dump_manager_(initialize_memory_dump_manager) { 68 initialize_memory_dump_manager_(initialize_memory_dump_manager) {
64 if (initialize_memory_dump_manager) { 69 if (initialize_memory_dump_manager) {
65 // TODO(primiano): the current state where the coordinator also creates a 70 // TODO(primiano): the current state where the coordinator also creates a
66 // client (ProcessLocalDumpManagerImpl) is contra-intuitive. BrowserMainLoop 71 // client (ProcessLocalDumpManagerImpl) is contra-intuitive. BrowserMainLoop
67 // should be doing this. 72 // should be doing this.
68 ProcessLocalDumpManagerImpl::CreateInstance( 73 ProcessLocalDumpManagerImpl::CreateInstance(
69 ProcessLocalDumpManagerImpl::Config(this, mojom::ProcessType::BROWSER)); 74 ProcessLocalDumpManagerImpl::Config(this, mojom::ProcessType::BROWSER));
70 base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id( 75 base::trace_event::MemoryDumpManager::GetInstance()->set_tracing_process_id(
71 mojom::kServiceTracingProcessId); 76 mojom::kServiceTracingProcessId);
72 } 77 }
78 process_map_.reset(new ProcessMap(connector));
73 g_coordinator_impl = this; 79 g_coordinator_impl = this;
74 } 80 }
75 81
82 service_manager::Identity CoordinatorImpl::GetDispatchContext() const {
83 return bindings_.dispatch_context();
84 }
85
76 CoordinatorImpl::~CoordinatorImpl() { 86 CoordinatorImpl::~CoordinatorImpl() {
77 g_coordinator_impl = nullptr; 87 g_coordinator_impl = nullptr;
78 } 88 }
79 89
80 void CoordinatorImpl::BindCoordinatorRequest( 90 void CoordinatorImpl::BindCoordinatorRequest(
81 const service_manager::BindSourceInfo& source_info, 91 const service_manager::BindSourceInfo& source_info,
82 mojom::CoordinatorRequest request) { 92 mojom::CoordinatorRequest request) {
83 DCHECK(thread_checker_.CalledOnValidThread()); 93 DCHECK(thread_checker_.CalledOnValidThread());
84 bindings_.AddBinding(this, std::move(request)); 94 bindings_.AddBinding(this, std::move(request), source_info.identity);
85 } 95 }
86 96
87 CoordinatorImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest( 97 CoordinatorImpl::QueuedMemoryDumpRequest::QueuedMemoryDumpRequest(
88 const base::trace_event::MemoryDumpRequestArgs args, 98 const base::trace_event::MemoryDumpRequestArgs args,
89 const RequestGlobalMemoryDumpCallback callback) 99 const RequestGlobalMemoryDumpCallback callback)
90 : args(args), callback(callback) {} 100 : args(args), callback(callback) {}
91 101
92 CoordinatorImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {} 102 CoordinatorImpl::QueuedMemoryDumpRequest::~QueuedMemoryDumpRequest() {}
93 103
94 void CoordinatorImpl::RequestGlobalMemoryDump( 104 void CoordinatorImpl::RequestGlobalMemoryDump(
95 const base::trace_event::MemoryDumpRequestArgs& args, 105 const base::trace_event::MemoryDumpRequestArgs& args,
96 const RequestGlobalMemoryDumpCallback& callback) { 106 const RequestGlobalMemoryDumpCallback& callback) {
97 DCHECK(thread_checker_.CalledOnValidThread()); 107 DCHECK(thread_checker_.CalledOnValidThread());
98 bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty(); 108 bool another_dump_already_in_progress = !queued_memory_dump_requests_.empty();
99 109
100 // If this is a periodic or peak memory dump request and there already is 110 // If this is a periodic or peak memory dump request and there already is
101 // another request in the queue with the same level of detail, there's no 111 // another request in the queue with the same level of detail, there's no
102 // point in enqueuing this request. 112 // point in enqueuing this request.
103 if (another_dump_already_in_progress && 113 if (another_dump_already_in_progress &&
104 args.dump_type != 114 args.dump_type !=
105 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED) { 115 base::trace_event::MemoryDumpType::EXPLICITLY_TRIGGERED &&
116 args.dump_type != base::trace_event::MemoryDumpType::SUMMARY_ONLY) {
106 for (const auto& request : queued_memory_dump_requests_) { 117 for (const auto& request : queued_memory_dump_requests_) {
107 if (request.args.level_of_detail == args.level_of_detail) { 118 if (request.args.level_of_detail == args.level_of_detail) {
108 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " (" 119 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix << " ("
109 << base::trace_event::MemoryDumpTypeToString(args.dump_type) 120 << base::trace_event::MemoryDumpTypeToString(args.dump_type)
110 << ") skipped because another dump request with the same " 121 << ") skipped because another dump request with the same "
111 "level of detail (" 122 "level of detail ("
112 << base::trace_event::MemoryDumpLevelOfDetailToString( 123 << base::trace_event::MemoryDumpLevelOfDetailToString(
113 args.level_of_detail) 124 args.level_of_detail)
114 << ") is already in the queue"; 125 << ") is already in the queue";
115 callback.Run(args.dump_guid, false /* success */, 126 callback.Run(args.dump_guid, false /* success */,
(...skipping 12 matching lines...) Expand all
128 139
129 PerformNextQueuedGlobalMemoryDump(); 140 PerformNextQueuedGlobalMemoryDump();
130 } 141 }
131 142
132 void CoordinatorImpl::RegisterProcessLocalDumpManager( 143 void CoordinatorImpl::RegisterProcessLocalDumpManager(
133 mojom::ProcessLocalDumpManagerPtr process_manager) { 144 mojom::ProcessLocalDumpManagerPtr process_manager) {
134 DCHECK(thread_checker_.CalledOnValidThread()); 145 DCHECK(thread_checker_.CalledOnValidThread());
135 process_manager.set_connection_error_handler( 146 process_manager.set_connection_error_handler(
136 base::Bind(&CoordinatorImpl::UnregisterProcessLocalDumpManager, 147 base::Bind(&CoordinatorImpl::UnregisterProcessLocalDumpManager,
137 base::Unretained(this), process_manager.get())); 148 base::Unretained(this), process_manager.get()));
138 auto result = process_managers_.insert( 149 mojom::ProcessLocalDumpManager* key = process_manager.get();
139 std::make_pair<mojom::ProcessLocalDumpManager*, 150 auto result = process_managers_.emplace(
140 mojom::ProcessLocalDumpManagerPtr>( 151 key, std::make_pair(std::move(process_manager), GetDispatchContext()));
141 process_manager.get(), std::move(process_manager)));
142 DCHECK(result.second); 152 DCHECK(result.second);
143 } 153 }
144 154
145 void CoordinatorImpl::UnregisterProcessLocalDumpManager( 155 void CoordinatorImpl::UnregisterProcessLocalDumpManager(
146 mojom::ProcessLocalDumpManager* process_manager) { 156 mojom::ProcessLocalDumpManager* process_manager) {
147 size_t num_deleted = process_managers_.erase(process_manager); 157 size_t num_deleted = process_managers_.erase(process_manager);
148 DCHECK(num_deleted == 1); 158 DCHECK(num_deleted == 1);
149 159
150 // Check if we are waiting for an ack from this process-local manager. 160 // Check if we are waiting for an ack from this process-local manager.
151 if (pending_process_managers_.find(process_manager) != 161 if (pending_process_managers_.find(process_manager) !=
152 pending_process_managers_.end()) { 162 pending_process_managers_.end()) {
153 DCHECK(!queued_memory_dump_requests_.empty()); 163 DCHECK(!queued_memory_dump_requests_.empty());
154 OnProcessMemoryDumpResponse( 164 OnProcessMemoryDumpResponse(
155 process_manager, queued_memory_dump_requests_.front().args.dump_guid, 165 process_manager, queued_memory_dump_requests_.front().args.dump_guid,
156 false /* success */, nullptr /* process_memory_dump */); 166 false /* success */, nullptr /* process_memory_dump */);
157 } 167 }
158 } 168 }
159 169
160 void CoordinatorImpl::PerformNextQueuedGlobalMemoryDump() { 170 void CoordinatorImpl::PerformNextQueuedGlobalMemoryDump() {
161 DCHECK(!queued_memory_dump_requests_.empty()); 171 DCHECK(!queued_memory_dump_requests_.empty());
162 const base::trace_event::MemoryDumpRequestArgs& args = 172 const base::trace_event::MemoryDumpRequestArgs& args =
163 queued_memory_dump_requests_.front().args; 173 queued_memory_dump_requests_.front().args;
164 174
165 // No need to treat the service process different than other processes. The 175 // No need to treat the service process different than other processes. The
166 // service process will register itself as a ProcessLocalDumpManager and will 176 // service process will register itself as a ProcessLocalDumpManager and
167 // be treated like other process-local managers. 177 // will be treated like other process-local managers.
168 pending_process_managers_.clear(); 178 pending_process_managers_.clear();
169 failed_memory_dump_count_ = 0; 179 failed_memory_dump_count_ = 0;
170 for (const auto& key_value : process_managers_) { 180 for (const auto& key_value : process_managers_) {
171 pending_process_managers_.insert(key_value.first); 181 pending_process_managers_.insert(key_value.first);
172 auto callback = base::Bind(&CoordinatorImpl::OnProcessMemoryDumpResponse, 182 auto callback = base::Bind(&CoordinatorImpl::OnProcessMemoryDumpResponse,
173 base::Unretained(this), key_value.first); 183 base::Unretained(this), key_value.first);
174 key_value.second->RequestProcessMemoryDump(args, callback); 184 key_value.second.first->RequestProcessMemoryDump(args, callback);
175 } 185 }
176 // Run the callback in case there are no process-local managers. 186 // Run the callback in case there are no process-local managers.
177 FinalizeGlobalMemoryDumpIfAllManagersReplied(); 187 FinalizeGlobalMemoryDumpIfAllManagersReplied();
178 } 188 }
179 189
180 void CoordinatorImpl::OnProcessMemoryDumpResponse( 190 void CoordinatorImpl::OnProcessMemoryDumpResponse(
181 mojom::ProcessLocalDumpManager* process_manager, 191 mojom::ProcessLocalDumpManager* process_manager,
182 uint64_t dump_guid, 192 uint64_t dump_guid,
183 bool success, 193 bool success,
184 mojom::ProcessMemoryDumpPtr process_memory_dump) { 194 mojom::ProcessMemoryDumpPtr process_memory_dump) {
185 auto it = pending_process_managers_.find(process_manager); 195 auto it = pending_process_managers_.find(process_manager);
186 196
187 if (queued_memory_dump_requests_.empty() || 197 if (queued_memory_dump_requests_.empty() ||
188 queued_memory_dump_requests_.front().args.dump_guid != dump_guid || 198 queued_memory_dump_requests_.front().args.dump_guid != dump_guid ||
189 it == pending_process_managers_.end()) { 199 it == pending_process_managers_.end()) {
190 VLOG(1) << "Received unexpected memory dump response: " << dump_guid; 200 VLOG(1) << "Received unexpected memory dump response: " << dump_guid;
191 return; 201 return;
192 } 202 }
193 if (process_memory_dump) { 203 if (process_memory_dump) {
204 base::ProcessId pid = base::kNullProcessId;
205 auto it = process_managers_.find(process_manager);
206 if (it != process_managers_.end()) {
207 pid = process_map_->GetProcessId(it->second.second);
208 }
209
194 queued_memory_dump_requests_.front().process_memory_dumps.push_back( 210 queued_memory_dump_requests_.front().process_memory_dumps.push_back(
195 std::move(process_memory_dump)); 211 std::make_pair(pid, std::move(process_memory_dump)));
196 } 212 }
197 213
198 pending_process_managers_.erase(it); 214 pending_process_managers_.erase(it);
199 215
200 if (!success) { 216 if (!success) {
201 ++failed_memory_dump_count_; 217 ++failed_memory_dump_count_;
202 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix 218 VLOG(1) << base::trace_event::MemoryDumpManager::kLogPrefix
203 << " failed because of NACK from provider"; 219 << " failed because of NACK from provider";
204 } 220 }
205 221
206 FinalizeGlobalMemoryDumpIfAllManagersReplied(); 222 FinalizeGlobalMemoryDumpIfAllManagersReplied();
207 } 223 }
208 224
209 void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { 225 void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() {
210 if (pending_process_managers_.size() > 0) 226 if (pending_process_managers_.size() > 0)
211 return; 227 return;
212 228
213 if (queued_memory_dump_requests_.empty()) { 229 if (queued_memory_dump_requests_.empty()) {
214 NOTREACHED(); 230 NOTREACHED();
215 return; 231 return;
216 } 232 }
217 233
218 std::map<base::ProcessId, mojom::ProcessMemoryDumpPtr> finalized_pmds; 234 std::map<base::ProcessId, mojom::ProcessMemoryDumpPtr> finalized_pmds;
219 for (auto& result : 235 for (auto& result :
220 queued_memory_dump_requests_.front().process_memory_dumps) { 236 queued_memory_dump_requests_.front().process_memory_dumps) {
221 // TODO(fmeawad): Write into correct map entry instead of always 237 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[result.first];
222 // to pid = 0.
223 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[0];
224 if (!pmd) 238 if (!pmd)
225 pmd = mojom::ProcessMemoryDump::New(); 239 pmd = mojom::ProcessMemoryDump::New();
226 pmd->chrome_dump = std::move(result->chrome_dump); 240 pmd->chrome_dump = std::move(result.second->chrome_dump);
227 241
228 // TODO(hjd): We should have a better way to tell if os_dump is filled. 242 // TODO(hjd): We should have a better way to tell if os_dump is filled.
229 if (result->os_dump.resident_set_kb > 0) { 243 if (result.second->os_dump.resident_set_kb > 0) {
230 pmd->os_dump = std::move(result->os_dump); 244 pmd->os_dump = std::move(result.second->os_dump);
231 } 245 }
232 246
233 for (auto& pair : result->extra_processes_dump) { 247 for (auto& pair : result.second->extra_processes_dump) {
234 base::ProcessId pid = pair.first; 248 base::ProcessId pid = pair.first;
235 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[pid]; 249 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[pid];
236 if (!pmd) 250 if (!pmd)
237 pmd = mojom::ProcessMemoryDump::New(); 251 pmd = mojom::ProcessMemoryDump::New();
238 pmd->os_dump = std::move(result->extra_processes_dump[pid]); 252 pmd->os_dump = std::move(result.second->extra_processes_dump[pid]);
239 } 253 }
254
255 pmd->process_type = result.second->process_type;
240 } 256 }
241 257
242 mojom::GlobalMemoryDumpPtr global_dump(mojom::GlobalMemoryDump::New()); 258 mojom::GlobalMemoryDumpPtr global_dump(mojom::GlobalMemoryDump::New());
243 for (auto& pair : finalized_pmds) { 259 for (auto& pair : finalized_pmds) {
244 // It's possible that the renderer has died but we still have an os_dump, 260 // It's possible that the renderer has died but we still have an os_dump,
245 // because those were comptued from the browser proces before the renderer 261 // because those were computed from the browser proces before the renderer
246 // died. We should skip these. 262 // died. We should skip these.
247 // TODO(hjd): We should have a better way to tell if a chrome_dump is 263 // TODO(hjd): We should have a better way to tell if a chrome_dump is
248 // filled. 264 // filled.
249 if (!pair.second->chrome_dump.malloc_total_kb) 265 if (!pair.second->chrome_dump.malloc_total_kb)
250 continue; 266 continue;
251 base::ProcessId pid = pair.first; 267 base::ProcessId pid = pair.first;
252 mojom::ProcessMemoryDumpPtr pmd = std::move(finalized_pmds[pid]); 268 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[pid];
253 pmd->private_footprint = CalculatePrivateFootprintKb(pmd->os_dump); 269 pmd->private_footprint = CalculatePrivateFootprintKb(pmd->os_dump);
254 global_dump->process_dumps.push_back(std::move(pmd)); 270 global_dump->process_dumps.push_back(std::move(pmd));
255 } 271 }
256 272
257 const auto& callback = queued_memory_dump_requests_.front().callback; 273 const auto& callback = queued_memory_dump_requests_.front().callback;
258 const bool global_success = failed_memory_dump_count_ == 0; 274 const bool global_success = failed_memory_dump_count_ == 0;
259 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, 275 callback.Run(queued_memory_dump_requests_.front().args.dump_guid,
260 global_success, std::move(global_dump)); 276 global_success, std::move(global_dump));
261 queued_memory_dump_requests_.pop_front(); 277 queued_memory_dump_requests_.pop_front();
262 278
263 // Schedule the next queued dump (if applicable). 279 // Schedule the next queued dump (if applicable).
264 if (!queued_memory_dump_requests_.empty()) { 280 if (!queued_memory_dump_requests_.empty()) {
265 base::ThreadTaskRunnerHandle::Get()->PostTask( 281 base::ThreadTaskRunnerHandle::Get()->PostTask(
266 FROM_HERE, 282 FROM_HERE,
267 base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump, 283 base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump,
268 base::Unretained(this))); 284 base::Unretained(this)));
269 } 285 }
270 } 286 }
271 287
272 } // namespace memory_instrumentation 288 } // namespace memory_instrumentation
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698