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

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

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

Powered by Google App Engine
This is Rietveld 408576698