OLD | NEW |
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 "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/location.h" | 9 #include "base/location.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/memory/ref_counted.h" | 11 #include "base/memory/ref_counted.h" |
12 #include "base/single_thread_task_runner.h" | 12 #include "base/single_thread_task_runner.h" |
13 #include "base/threading/platform_thread.h" | 13 #include "base/threading/platform_thread.h" |
14 #include "base/trace_event/memory_dump_manager.h" | 14 #include "base/trace_event/memory_dump_manager.h" |
15 #include "base/trace_event/memory_dump_request_args.h" | 15 #include "base/trace_event/memory_dump_request_args.h" |
16 #include "services/resource_coordinator/public/cpp/memory/process_local_dump_man
ager_impl.h" | 16 #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" | 17 #include "services/resource_coordinator/public/interfaces/memory/constants.mojom
.h" |
18 #include "services/resource_coordinator/public/interfaces/memory/memory_instrume
ntation.mojom.h" | 18 #include "services/resource_coordinator/public/interfaces/memory/memory_instrume
ntation.mojom.h" |
19 | 19 |
| 20 #if defined(OS_MACOSX) && !defined(OS_IOS) |
| 21 #include "base/mac/mac_util.h" |
| 22 #endif |
| 23 |
20 namespace { | 24 namespace { |
21 | 25 |
22 memory_instrumentation::CoordinatorImpl* g_coordinator_impl; | 26 memory_instrumentation::CoordinatorImpl* g_coordinator_impl; |
23 | 27 |
| 28 uint32_t CalculatePrivateFootprintKb( |
| 29 base::trace_event::MemoryDumpCallbackResult::OSMemDump& os_dump) { |
| 30 #if defined(OS_LINUX) || defined(OS_ANDROID) |
| 31 uint64_t rss_anon_bytes = os_dump.platform_private_footprint.rss_anon_bytes; |
| 32 uint64_t vm_swap_bytes = os_dump.platform_private_footprint.vm_swap_bytes; |
| 33 return (rss_anon_bytes + vm_swap_bytes) / 1024; |
| 34 #elif defined(OS_MACOSX) |
| 35 // TODO(erikchen): This calculation is close, but not fully accurate. It |
| 36 // overcounts by anonymous shared memory. |
| 37 if (base::mac::IsAtLeastOS10_12()) { |
| 38 uint64_t phys_footprint_bytes = |
| 39 os_dump.platform_private_footprint.phys_footprint_bytes; |
| 40 return phys_footprint_bytes / 1024; |
| 41 } else { |
| 42 uint64_t internal_bytes = os_dump.platform_private_footprint.internal_bytes; |
| 43 uint64_t compressed_bytes = |
| 44 os_dump.platform_private_footprint.compressed_bytes; |
| 45 return (internal_bytes + compressed_bytes) / 1024; |
| 46 } |
| 47 #else |
| 48 return 0; |
| 49 #endif |
| 50 } |
| 51 |
24 } // namespace | 52 } // namespace |
25 | 53 |
26 namespace memory_instrumentation { | 54 namespace memory_instrumentation { |
27 | 55 |
28 // static | 56 // static |
29 CoordinatorImpl* CoordinatorImpl::GetInstance() { | 57 CoordinatorImpl* CoordinatorImpl::GetInstance() { |
30 return g_coordinator_impl; | 58 return g_coordinator_impl; |
31 } | 59 } |
32 | 60 |
33 CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager) | 61 CoordinatorImpl::CoordinatorImpl(bool initialize_memory_dump_manager) |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
180 | 208 |
181 void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { | 209 void CoordinatorImpl::FinalizeGlobalMemoryDumpIfAllManagersReplied() { |
182 if (pending_process_managers_.size() > 0) | 210 if (pending_process_managers_.size() > 0) |
183 return; | 211 return; |
184 | 212 |
185 if (queued_memory_dump_requests_.empty()) { | 213 if (queued_memory_dump_requests_.empty()) { |
186 NOTREACHED(); | 214 NOTREACHED(); |
187 return; | 215 return; |
188 } | 216 } |
189 | 217 |
190 // TODO(hjd,fmeawad): At this point the |process_memory_dumps| accumulated in | 218 std::map<base::ProcessId, mojom::ProcessMemoryDumpPtr> finalized_pmds; |
191 // queued_memory_dump_requests_.front() should be normalized (merge | 219 for (auto& result : |
192 // |extra_process_dump|, compute CMM) into a GlobalMemoryDumpPtr and passed | 220 queued_memory_dump_requests_.front().process_memory_dumps) { |
193 // below. | 221 // TODO(fmeawad): Write into correct map entry instead of always |
| 222 // to pid = 0. |
| 223 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[0]; |
| 224 if (!pmd) |
| 225 pmd = mojom::ProcessMemoryDump::New(); |
| 226 pmd->chrome_dump = std::move(result->chrome_dump); |
| 227 |
| 228 // TODO(hjd): We should have a better way to tell if os_dump is filled. |
| 229 if (result->os_dump.resident_set_kb > 0) { |
| 230 pmd->os_dump = std::move(result->os_dump); |
| 231 } |
| 232 |
| 233 for (auto& pair : result->extra_processes_dump) { |
| 234 base::ProcessId pid = pair.first; |
| 235 mojom::ProcessMemoryDumpPtr& pmd = finalized_pmds[pid]; |
| 236 if (!pmd) |
| 237 pmd = mojom::ProcessMemoryDump::New(); |
| 238 pmd->os_dump = std::move(result->extra_processes_dump[pid]); |
| 239 } |
| 240 } |
| 241 |
| 242 mojom::GlobalMemoryDumpPtr global_dump(mojom::GlobalMemoryDump::New()); |
| 243 for (auto& pair : finalized_pmds) { |
| 244 // 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 |
| 246 // died. We should skip these. |
| 247 // TODO(hjd): We should have a better way to tell if a chrome_dump is |
| 248 // filled. |
| 249 if (!pair.second->chrome_dump.malloc_total_kb) |
| 250 continue; |
| 251 base::ProcessId pid = pair.first; |
| 252 mojom::ProcessMemoryDumpPtr pmd = std::move(finalized_pmds[pid]); |
| 253 pmd->private_footprint = CalculatePrivateFootprintKb(pmd->os_dump); |
| 254 global_dump->process_dumps.push_back(std::move(pmd)); |
| 255 } |
194 | 256 |
195 const auto& callback = queued_memory_dump_requests_.front().callback; | 257 const auto& callback = queued_memory_dump_requests_.front().callback; |
196 const bool global_success = failed_memory_dump_count_ == 0; | 258 const bool global_success = failed_memory_dump_count_ == 0; |
197 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, | 259 callback.Run(queued_memory_dump_requests_.front().args.dump_guid, |
198 global_success, nullptr /* global_memory_dump */); | 260 global_success, std::move(global_dump)); |
199 queued_memory_dump_requests_.pop_front(); | 261 queued_memory_dump_requests_.pop_front(); |
200 | 262 |
201 // Schedule the next queued dump (if applicable). | 263 // Schedule the next queued dump (if applicable). |
202 if (!queued_memory_dump_requests_.empty()) { | 264 if (!queued_memory_dump_requests_.empty()) { |
203 base::ThreadTaskRunnerHandle::Get()->PostTask( | 265 base::ThreadTaskRunnerHandle::Get()->PostTask( |
204 FROM_HERE, | 266 FROM_HERE, |
205 base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump, | 267 base::Bind(&CoordinatorImpl::PerformNextQueuedGlobalMemoryDump, |
206 base::Unretained(this))); | 268 base::Unretained(this))); |
207 } | 269 } |
208 } | 270 } |
209 | 271 |
210 } // namespace memory_instrumentation | 272 } // namespace memory_instrumentation |
OLD | NEW |