| 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 30 matching lines...) Expand all Loading... |
| 41 const int kTraceEventNumArgs = 1; | 41 const int kTraceEventNumArgs = 1; |
| 42 const char* kTraceEventArgNames[] = {"dumps"}; | 42 const char* kTraceEventArgNames[] = {"dumps"}; |
| 43 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; | 43 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; |
| 44 | 44 |
| 45 StaticAtomicSequenceNumber g_next_guid; | 45 StaticAtomicSequenceNumber g_next_guid; |
| 46 uint32 g_periodic_dumps_count = 0; | 46 uint32 g_periodic_dumps_count = 0; |
| 47 uint32 g_heavy_dumps_rate = 0; | 47 uint32 g_heavy_dumps_rate = 0; |
| 48 MemoryDumpManager* g_instance_for_testing = nullptr; | 48 MemoryDumpManager* g_instance_for_testing = nullptr; |
| 49 | 49 |
| 50 void RequestPeriodicGlobalDump() { | 50 void RequestPeriodicGlobalDump() { |
| 51 MemoryDumpArgs::LevelOfDetail dump_level_of_detail; | 51 MemoryDumpLevelOfDetail level_of_detail; |
| 52 if (g_heavy_dumps_rate == 0) { | 52 if (g_heavy_dumps_rate == 0) { |
| 53 dump_level_of_detail = MemoryDumpArgs::LevelOfDetail::LOW; | 53 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; |
| 54 } else { | 54 } else { |
| 55 dump_level_of_detail = g_periodic_dumps_count == 0 | 55 level_of_detail = g_periodic_dumps_count == 0 |
| 56 ? MemoryDumpArgs::LevelOfDetail::HIGH | 56 ? MemoryDumpLevelOfDetail::DETAILED |
| 57 : MemoryDumpArgs::LevelOfDetail::LOW; | 57 : MemoryDumpLevelOfDetail::LIGHT; |
| 58 | 58 |
| 59 if (++g_periodic_dumps_count == g_heavy_dumps_rate) | 59 if (++g_periodic_dumps_count == g_heavy_dumps_rate) |
| 60 g_periodic_dumps_count = 0; | 60 g_periodic_dumps_count = 0; |
| 61 } | 61 } |
| 62 | 62 |
| 63 MemoryDumpArgs dump_args = {dump_level_of_detail}; | |
| 64 MemoryDumpManager::GetInstance()->RequestGlobalDump( | 63 MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| 65 MemoryDumpType::PERIODIC_INTERVAL, dump_args); | 64 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
| 66 } | 65 } |
| 67 | 66 |
| 68 } // namespace | 67 } // namespace |
| 69 | 68 |
| 70 // static | 69 // static |
| 71 const char* const MemoryDumpManager::kTraceCategory = | 70 const char* const MemoryDumpManager::kTraceCategory = |
| 72 TRACE_DISABLED_BY_DEFAULT("memory-infra"); | 71 TRACE_DISABLED_BY_DEFAULT("memory-infra"); |
| 73 | 72 |
| 74 // static | 73 // static |
| 75 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; | 74 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; |
| (...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 197 // race-free. If you hit this DCHECK, your MDP has a bug. | 196 // race-free. If you hit this DCHECK, your MDP has a bug. |
| 198 DCHECK_IMPLIES( | 197 DCHECK_IMPLIES( |
| 199 subtle::NoBarrier_Load(&memory_tracing_enabled_), | 198 subtle::NoBarrier_Load(&memory_tracing_enabled_), |
| 200 mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread()) | 199 mdp_iter->task_runner && mdp_iter->task_runner->BelongsToCurrentThread()) |
| 201 << "The MemoryDumpProvider attempted to unregister itself in a racy way. " | 200 << "The MemoryDumpProvider attempted to unregister itself in a racy way. " |
| 202 << "Please file a crbug."; | 201 << "Please file a crbug."; |
| 203 | 202 |
| 204 mdp_iter->unregistered = true; | 203 mdp_iter->unregistered = true; |
| 205 } | 204 } |
| 206 | 205 |
| 207 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, | 206 void MemoryDumpManager::RequestGlobalDump( |
| 208 const MemoryDumpArgs& dump_args, | 207 MemoryDumpType dump_type, |
| 209 const MemoryDumpCallback& callback) { | 208 MemoryDumpLevelOfDetail level_of_detail, |
| 209 const MemoryDumpCallback& callback) { |
| 210 // Bail out immediately if tracing is not enabled at all. | 210 // Bail out immediately if tracing is not enabled at all. |
| 211 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) { | 211 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_))) { |
| 212 if (!callback.is_null()) | 212 if (!callback.is_null()) |
| 213 callback.Run(0u /* guid */, false /* success */); | 213 callback.Run(0u /* guid */, false /* success */); |
| 214 return; | 214 return; |
| 215 } | 215 } |
| 216 | 216 |
| 217 const uint64 guid = | 217 const uint64 guid = |
| 218 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 218 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
| 219 | 219 |
| 220 // Technically there is no need to grab the |lock_| here as the delegate is | 220 // Technically there is no need to grab the |lock_| here as the delegate is |
| 221 // long-lived and can only be set by Initialize(), which is locked and | 221 // long-lived and can only be set by Initialize(), which is locked and |
| 222 // necessarily happens before memory_tracing_enabled_ == true. | 222 // necessarily happens before memory_tracing_enabled_ == true. |
| 223 // Not taking the |lock_|, though, is lakely make TSan barf and, at this point | 223 // Not taking the |lock_|, though, is lakely make TSan barf and, at this point |
| 224 // (memory-infra is enabled) we're not in the fast-path anymore. | 224 // (memory-infra is enabled) we're not in the fast-path anymore. |
| 225 MemoryDumpManagerDelegate* delegate; | 225 MemoryDumpManagerDelegate* delegate; |
| 226 { | 226 { |
| 227 AutoLock lock(lock_); | 227 AutoLock lock(lock_); |
| 228 delegate = delegate_; | 228 delegate = delegate_; |
| 229 } | 229 } |
| 230 | 230 |
| 231 // The delegate will coordinate the IPC broadcast and at some point invoke | 231 // The delegate will coordinate the IPC broadcast and at some point invoke |
| 232 // CreateProcessDump() to get a dump for the current process. | 232 // CreateProcessDump() to get a dump for the current process. |
| 233 MemoryDumpRequestArgs args = {guid, dump_type, dump_args}; | 233 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; |
| 234 delegate->RequestGlobalMemoryDump(args, callback); | 234 delegate->RequestGlobalMemoryDump(args, callback); |
| 235 } | 235 } |
| 236 | 236 |
| 237 void MemoryDumpManager::RequestGlobalDump(MemoryDumpType dump_type, | 237 void MemoryDumpManager::RequestGlobalDump( |
| 238 const MemoryDumpArgs& dump_args) { | 238 MemoryDumpType dump_type, |
| 239 RequestGlobalDump(dump_type, dump_args, MemoryDumpCallback()); | 239 MemoryDumpLevelOfDetail level_of_detail) { |
| 240 RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback()); |
| 240 } | 241 } |
| 241 | 242 |
| 242 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, | 243 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, |
| 243 const MemoryDumpCallback& callback) { | 244 const MemoryDumpCallback& callback) { |
| 244 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; | 245 scoped_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; |
| 245 { | 246 { |
| 246 AutoLock lock(lock_); | 247 AutoLock lock(lock_); |
| 247 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( | 248 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( |
| 248 args, dump_providers_.begin(), session_state_, callback)); | 249 args, dump_providers_.begin(), session_state_, callback)); |
| 249 } | 250 } |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 312 mdp_info->disabled = true; | 313 mdp_info->disabled = true; |
| 313 return AbortDumpLocked(callback, callback_task_runner, dump_guid); | 314 return AbortDumpLocked(callback, callback_task_runner, dump_guid); |
| 314 } | 315 } |
| 315 } // AutoLock(lock_) | 316 } // AutoLock(lock_) |
| 316 | 317 |
| 317 // Invoke the dump provider without holding the |lock_|. | 318 // Invoke the dump provider without holding the |lock_|. |
| 318 bool finalize = false; | 319 bool finalize = false; |
| 319 bool dump_successful = false; | 320 bool dump_successful = false; |
| 320 | 321 |
| 321 if (!skip_dump) { | 322 if (!skip_dump) { |
| 322 dump_successful = mdp->OnMemoryDump(pmd_async_state->req_args.dump_args, | 323 MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail}; |
| 323 &pmd_async_state->process_memory_dump); | 324 dump_successful = |
| 325 mdp->OnMemoryDump(args, &pmd_async_state->process_memory_dump); |
| 324 } | 326 } |
| 325 | 327 |
| 326 { | 328 { |
| 327 AutoLock lock(lock_); | 329 AutoLock lock(lock_); |
| 328 auto mdp_info = pmd_async_state->next_dump_provider; | 330 auto mdp_info = pmd_async_state->next_dump_provider; |
| 329 if (dump_successful) { | 331 if (dump_successful) { |
| 330 mdp_info->consecutive_failures = 0; | 332 mdp_info->consecutive_failures = 0; |
| 331 } else if (!skip_dump) { | 333 } else if (!skip_dump) { |
| 332 ++mdp_info->consecutive_failures; | 334 ++mdp_info->consecutive_failures; |
| 333 if (mdp_info->consecutive_failures >= kMaxConsecutiveFailuresCount) { | 335 if (mdp_info->consecutive_failures >= kMaxConsecutiveFailuresCount) { |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 441 const TraceConfig::MemoryDumpConfig& config_list = | 443 const TraceConfig::MemoryDumpConfig& config_list = |
| 442 trace_config.memory_dump_config(); | 444 trace_config.memory_dump_config(); |
| 443 if (config_list.empty()) | 445 if (config_list.empty()) |
| 444 return; | 446 return; |
| 445 | 447 |
| 446 uint32 min_timer_period_ms = std::numeric_limits<uint32>::max(); | 448 uint32 min_timer_period_ms = std::numeric_limits<uint32>::max(); |
| 447 uint32 heavy_dump_period_ms = 0; | 449 uint32 heavy_dump_period_ms = 0; |
| 448 DCHECK_LE(config_list.size(), 2u); | 450 DCHECK_LE(config_list.size(), 2u); |
| 449 for (const TraceConfig::MemoryDumpTriggerConfig& config : config_list) { | 451 for (const TraceConfig::MemoryDumpTriggerConfig& config : config_list) { |
| 450 DCHECK(config.periodic_interval_ms); | 452 DCHECK(config.periodic_interval_ms); |
| 451 if (config.level_of_detail == MemoryDumpArgs::LevelOfDetail::HIGH) | 453 if (config.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) |
| 452 heavy_dump_period_ms = config.periodic_interval_ms; | 454 heavy_dump_period_ms = config.periodic_interval_ms; |
| 453 min_timer_period_ms = | 455 min_timer_period_ms = |
| 454 std::min(min_timer_period_ms, config.periodic_interval_ms); | 456 std::min(min_timer_period_ms, config.periodic_interval_ms); |
| 455 } | 457 } |
| 456 DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms); | 458 DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms); |
| 457 g_heavy_dumps_rate = heavy_dump_period_ms / min_timer_period_ms; | 459 g_heavy_dumps_rate = heavy_dump_period_ms / min_timer_period_ms; |
| 458 | 460 |
| 459 periodic_dump_timer_.Start(FROM_HERE, | 461 periodic_dump_timer_.Start(FROM_HERE, |
| 460 TimeDelta::FromMilliseconds(min_timer_period_ms), | 462 TimeDelta::FromMilliseconds(min_timer_period_ms), |
| 461 base::Bind(&RequestPeriodicGlobalDump)); | 463 base::Bind(&RequestPeriodicGlobalDump)); |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 next_dump_provider(next_dump_provider), | 503 next_dump_provider(next_dump_provider), |
| 502 callback(callback), | 504 callback(callback), |
| 503 task_runner(MessageLoop::current()->task_runner()) { | 505 task_runner(MessageLoop::current()->task_runner()) { |
| 504 } | 506 } |
| 505 | 507 |
| 506 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { | 508 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { |
| 507 } | 509 } |
| 508 | 510 |
| 509 } // namespace trace_event | 511 } // namespace trace_event |
| 510 } // namespace base | 512 } // namespace base |
| OLD | NEW |