OLD | NEW |
1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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 "base/trace_event/memory_dump_manager.h" | 5 #include "base/trace_event/memory_dump_manager.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 | 8 |
9 #include "base/atomic_sequence_num.h" | 9 #include "base/atomic_sequence_num.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 namespace base { | 36 namespace base { |
37 namespace trace_event { | 37 namespace trace_event { |
38 | 38 |
39 namespace { | 39 namespace { |
40 | 40 |
41 // TODO(primiano): this should be smarter and should do something similar to | 41 // TODO(primiano): this should be smarter and should do something similar to |
42 // trace event synthetic delays. | 42 // trace event synthetic delays. |
43 const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra"); | 43 const char kTraceCategory[] = TRACE_DISABLED_BY_DEFAULT("memory-infra"); |
44 | 44 |
45 // Throttle mmaps at a rate of once every kHeavyMmapsDumpsRate standard dumps. | 45 // Throttle mmaps at a rate of once every kHeavyMmapsDumpsRate standard dumps. |
46 const int kHeavyMmapsDumpsRate = 8; // 250 ms * 8 = 2000 ms. | 46 const int kHeavyDumpsRate = 8; // 250 ms * 8 = 2000 ms. |
47 const int kDumpIntervalMs = 250; | 47 const int kDumpIntervalMs = 250; |
48 const int kTraceEventNumArgs = 1; | 48 const int kTraceEventNumArgs = 1; |
49 const char* kTraceEventArgNames[] = {"dumps"}; | 49 const char* kTraceEventArgNames[] = {"dumps"}; |
50 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; | 50 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; |
51 | 51 |
52 StaticAtomicSequenceNumber g_next_guid; | 52 StaticAtomicSequenceNumber g_next_guid; |
53 uint32 g_periodic_dumps_count = 0; | 53 uint32 g_periodic_dumps_count = 0; |
54 MemoryDumpManager* g_instance_for_testing = nullptr; | 54 MemoryDumpManager* g_instance_for_testing = nullptr; |
55 MemoryDumpProvider* g_mmaps_dump_provider = nullptr; | |
56 | 55 |
57 void RequestPeriodicGlobalDump() { | 56 void RequestPeriodicGlobalDump() { |
58 MemoryDumpType dump_type = g_periodic_dumps_count == 0 | 57 MemoryDumpArgs::LevelOfDetail dump_level_of_detail = |
59 ? MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS | 58 g_periodic_dumps_count == 0 ? MemoryDumpArgs::LevelOfDetail::HIGH |
60 : MemoryDumpType::PERIODIC_INTERVAL; | 59 : MemoryDumpArgs::LevelOfDetail::LOW; |
61 if (++g_periodic_dumps_count == kHeavyMmapsDumpsRate) | 60 if (++g_periodic_dumps_count == kHeavyDumpsRate) |
62 g_periodic_dumps_count = 0; | 61 g_periodic_dumps_count = 0; |
63 | 62 |
64 MemoryDumpManager::GetInstance()->RequestGlobalDump(dump_type); | 63 MemoryDumpArgs dump_args = {dump_level_of_detail}; |
| 64 MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| 65 MemoryDumpType::PERIODIC_INTERVAL, dump_args); |
65 } | 66 } |
66 | 67 |
67 } // namespace | 68 } // namespace |
68 | 69 |
69 // static | 70 // static |
70 const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory; | 71 const char* const MemoryDumpManager::kTraceCategoryForTesting = kTraceCategory; |
71 | 72 |
72 // static | 73 // static |
73 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; | 74 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; |
74 | 75 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 | 112 |
112 if (skip_core_dumpers_auto_registration_for_testing_) | 113 if (skip_core_dumpers_auto_registration_for_testing_) |
113 return; | 114 return; |
114 | 115 |
115 // Enable the core dump providers. | 116 // Enable the core dump providers. |
116 #if !defined(OS_NACL) | 117 #if !defined(OS_NACL) |
117 RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance()); | 118 RegisterDumpProvider(ProcessMemoryTotalsDumpProvider::GetInstance()); |
118 #endif | 119 #endif |
119 | 120 |
120 #if defined(OS_LINUX) || defined(OS_ANDROID) | 121 #if defined(OS_LINUX) || defined(OS_ANDROID) |
121 g_mmaps_dump_provider = ProcessMemoryMapsDumpProvider::GetInstance(); | 122 RegisterDumpProvider(ProcessMemoryMapsDumpProvider::GetInstance()); |
122 RegisterDumpProvider(g_mmaps_dump_provider); | |
123 RegisterDumpProvider(MallocDumpProvider::GetInstance()); | 123 RegisterDumpProvider(MallocDumpProvider::GetInstance()); |
124 system_allocator_pool_name_ = MallocDumpProvider::kAllocatedObjects; | 124 system_allocator_pool_name_ = MallocDumpProvider::kAllocatedObjects; |
125 #endif | 125 #endif |
126 | 126 |
127 #if defined(OS_ANDROID) | 127 #if defined(OS_ANDROID) |
128 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance()); | 128 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance()); |
129 #endif | 129 #endif |
130 | 130 |
131 #if defined(OS_WIN) | 131 #if defined(OS_WIN) |
132 RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); | 132 RegisterDumpProvider(WinHeapDumpProvider::GetInstance()); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 DCHECK_IMPLIES( | 173 DCHECK_IMPLIES( |
174 subtle::NoBarrier_Load(&memory_tracing_enabled_), | 174 subtle::NoBarrier_Load(&memory_tracing_enabled_), |
175 mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread()) | 175 mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread()) |
176 << "The MemoryDumpProvider attempted to unregister itself in a racy way. " | 176 << "The MemoryDumpProvider attempted to unregister itself in a racy way. " |
177 << "Please file a crbug."; | 177 << "Please file a crbug."; |
178 | 178 |
179 dump_providers_.erase(mdp_iter); | 179 dump_providers_.erase(mdp_iter); |
180 did_unregister_dump_provider_ = true; | 180 did_unregister_dump_provider_ = true; |
181 } | 181 } |
182 | 182 |
183 void MemoryDumpManager::RequestGlobalDump( | 183 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, |
184 MemoryDumpType dump_type, | 184 const MemoryDumpArgs& dump_args, |
185 const MemoryDumpCallback& callback) { | 185 const MemoryDumpCallback& callback) { |
186 // Bail out immediately if tracing is not enabled at all. | 186 // Bail out immediately if tracing is not enabled at all. |
187 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) { | 187 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) { |
188 if (!callback.is_null()) | 188 if (!callback.is_null()) |
189 callback.Run(0u /* guid */, false /* success */); | 189 callback.Run(0u /* guid */, false /* success */); |
190 return; | 190 return; |
191 } | 191 } |
192 | 192 |
193 const uint64 guid = | 193 const uint64 guid = |
194 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 194 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
195 | 195 |
196 // The delegate_ is supposed to be thread safe, immutable and long lived. | 196 // The delegate_ is supposed to be thread safe, immutable and long lived. |
197 // No need to keep the lock after we ensure that a delegate has been set. | 197 // No need to keep the lock after we ensure that a delegate has been set. |
198 MemoryDumpManagerDelegate* delegate; | 198 MemoryDumpManagerDelegate* delegate; |
199 { | 199 { |
200 AutoLock lock(lock_); | 200 AutoLock lock(lock_); |
201 delegate = delegate_; | 201 delegate = delegate_; |
202 } | 202 } |
203 | 203 |
204 if (delegate) { | 204 if (delegate) { |
205 // The delegate is in charge to coordinate the request among all the | 205 // The delegate is in charge to coordinate the request among all the |
206 // processes and call the CreateLocalDumpPoint on the local process. | 206 // processes and call the CreateLocalDumpPoint on the local process. |
207 MemoryDumpRequestArgs args = {guid, dump_type}; | 207 MemoryDumpRequestArgs args = {guid, dump_type, dump_args}; |
208 delegate->RequestGlobalMemoryDump(args, callback); | 208 delegate->RequestGlobalMemoryDump(args, callback); |
209 } else if (!callback.is_null()) { | 209 } else if (!callback.is_null()) { |
210 callback.Run(guid, false /* success */); | 210 callback.Run(guid, false /* success */); |
211 } | 211 } |
212 } | 212 } |
213 | 213 |
214 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type) { | 214 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, |
215 RequestGlobalDump(dump_type, MemoryDumpCallback()); | 215 const MemoryDumpArgs& dump_args) { |
| 216 RequestGlobalDump(dump_type, dump_args, MemoryDumpCallback()); |
216 } | 217 } |
217 | 218 |
218 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, | 219 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, |
219 const MemoryDumpCallback& callback) { | 220 const MemoryDumpCallback& callback) { |
220 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; | 221 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; |
221 { | 222 { |
222 AutoLock lock(lock_); | 223 AutoLock lock(lock_); |
223 did_unregister_dump_provider_ = false; | 224 did_unregister_dump_provider_ = false; |
224 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 225 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
225 args, dump_providers_.begin(), session_state_, callback)); | 226 args, dump_providers_.begin(), session_state_, callback)); |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
266 if (did_unregister_dump_provider_) { | 267 if (did_unregister_dump_provider_) { |
267 return AbortDumpLocked(pmd_async_state->callback, | 268 return AbortDumpLocked(pmd_async_state->callback, |
268 pmd_async_state->task_runner, | 269 pmd_async_state->task_runner, |
269 pmd_async_state->req_args.dump_guid); | 270 pmd_async_state->req_args.dump_guid); |
270 } | 271 } |
271 | 272 |
272 auto* mdp_info = &*pmd_async_state->next_dump_provider; | 273 auto* mdp_info = &*pmd_async_state->next_dump_provider; |
273 mdp = mdp_info->dump_provider; | 274 mdp = mdp_info->dump_provider; |
274 if (mdp_info->disabled) { | 275 if (mdp_info->disabled) { |
275 skip_dump = true; | 276 skip_dump = true; |
276 } else if (mdp == g_mmaps_dump_provider && | |
277 pmd_async_state->req_args.dump_type != | |
278 MemoryDumpType::PERIODIC_INTERVAL_WITH_MMAPS && | |
279 pmd_async_state->req_args.dump_type != | |
280 MemoryDumpType::EXPLICITLY_TRIGGERED) { | |
281 // Mmaps dumping is very heavyweight and cannot be performed at the same | |
282 // rate of other dumps. TODO(primiano): this is a hack and should be | |
283 // cleaned up as part of crbug.com/499731. | |
284 skip_dump = true; | |
285 } else if (mdp_info->task_runner && | 277 } else if (mdp_info->task_runner && |
286 !mdp_info->task_runner->BelongsToCurrentThread()) { | 278 !mdp_info->task_runner->BelongsToCurrentThread()) { |
287 // It's time to hop onto another thread. | 279 // It's time to hop onto another thread. |
288 | 280 |
289 // Copy the callback + arguments just for the unlikley case in which | 281 // Copy the callback + arguments just for the unlikley case in which |
290 // PostTask fails. In such case the Bind helper will destroy the | 282 // PostTask fails. In such case the Bind helper will destroy the |
291 // pmd_async_state and we must keep a copy of the fields to notify the | 283 // pmd_async_state and we must keep a copy of the fields to notify the |
292 // abort. | 284 // abort. |
293 MemoryDumpCallback callback = pmd_async_state->callback; | 285 MemoryDumpCallback callback = pmd_async_state->callback; |
294 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 286 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
(...skipping 10 matching lines...) Expand all Loading... |
305 // disable the dump provider and abort this dump. | 297 // disable the dump provider and abort this dump. |
306 mdp_info->disabled = true; | 298 mdp_info->disabled = true; |
307 return AbortDumpLocked(callback, callback_task_runner, dump_guid); | 299 return AbortDumpLocked(callback, callback_task_runner, dump_guid); |
308 } | 300 } |
309 } // AutoLock(lock_) | 301 } // AutoLock(lock_) |
310 | 302 |
311 // Invoke the dump provider without holding the |lock_|. | 303 // Invoke the dump provider without holding the |lock_|. |
312 bool finalize = false; | 304 bool finalize = false; |
313 bool dump_successful = false; | 305 bool dump_successful = false; |
314 | 306 |
315 // TODO(ssid): Change RequestGlobalDump to use MemoryDumpArgs along with | |
316 // MemoryDumpType to get request for light / heavy dump, and remove this | |
317 // constant. | |
318 if (!skip_dump) { | 307 if (!skip_dump) { |
319 MemoryDumpArgs dump_args = {MemoryDumpArgs::LevelOfDetail::HIGH}; | 308 dump_successful = mdp->OnMemoryDump(pmd_async_state->req_args.dump_args, |
320 dump_successful = | 309 &pmd_async_state->process_memory_dump); |
321 mdp->OnMemoryDump(dump_args, &pmd_async_state->process_memory_dump); | |
322 } | 310 } |
323 | 311 |
324 { | 312 { |
325 AutoLock lock(lock_); | 313 AutoLock lock(lock_); |
326 if (did_unregister_dump_provider_) { | 314 if (did_unregister_dump_provider_) { |
327 return AbortDumpLocked(pmd_async_state->callback, | 315 return AbortDumpLocked(pmd_async_state->callback, |
328 pmd_async_state->task_runner, | 316 pmd_async_state->task_runner, |
329 pmd_async_state->req_args.dump_guid); | 317 pmd_async_state->req_args.dump_guid); |
330 } | 318 } |
331 auto* mdp_info = &*pmd_async_state->next_dump_provider; | 319 auto* mdp_info = &*pmd_async_state->next_dump_provider; |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 next_dump_provider(next_dump_provider), | 470 next_dump_provider(next_dump_provider), |
483 callback(callback), | 471 callback(callback), |
484 task_runner(MessageLoop::current()->task_runner()) { | 472 task_runner(MessageLoop::current()->task_runner()) { |
485 } | 473 } |
486 | 474 |
487 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { | 475 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { |
488 } | 476 } |
489 | 477 |
490 } // namespace trace_event | 478 } // namespace trace_event |
491 } // namespace base | 479 } // namespace base |
OLD | NEW |