Chromium Code Reviews| 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 #include <utility> | 8 #include <utility> |
| 9 | 9 |
| 10 #include "base/atomic_sequence_num.h" | 10 #include "base/atomic_sequence_num.h" |
| 11 #include "base/base_switches.h" | 11 #include "base/base_switches.h" |
| 12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
| 13 #include "base/compiler_specific.h" | 13 #include "base/compiler_specific.h" |
| 14 #include "base/debug/debugging_flags.h" | 14 #include "base/debug/debugging_flags.h" |
| 15 #include "base/debug/stack_trace.h" | 15 #include "base/debug/stack_trace.h" |
| 16 #include "base/memory/ptr_util.h" | 16 #include "base/memory/ptr_util.h" |
| 17 #include "base/threading/thread.h" | 17 #include "base/threading/thread.h" |
| 18 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
| 19 #include "base/timer/timer.h" | |
|
Primiano Tucci (use gerrit)
2016/06/02 20:24:04
I think these are conflicts with your other CLs ri
ssid
2016/06/03 01:59:46
Oh I removed this intentionally because this is in
| |
| 20 #include "base/trace_event/heap_profiler.h" | 19 #include "base/trace_event/heap_profiler.h" |
| 21 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 20 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
| 22 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 21 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
| 23 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" | 22 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
| 24 #include "base/trace_event/malloc_dump_provider.h" | 23 #include "base/trace_event/malloc_dump_provider.h" |
| 25 #include "base/trace_event/memory_dump_provider.h" | 24 #include "base/trace_event/memory_dump_provider.h" |
| 26 #include "base/trace_event/memory_dump_session_state.h" | 25 #include "base/trace_event/memory_dump_session_state.h" |
| 26 #include "base/trace_event/memory_infra_background_whitelist.h" | |
| 27 #include "base/trace_event/process_memory_dump.h" | 27 #include "base/trace_event/process_memory_dump.h" |
| 28 #include "base/trace_event/trace_event.h" | 28 #include "base/trace_event/trace_event.h" |
| 29 #include "base/trace_event/trace_event_argument.h" | 29 #include "base/trace_event/trace_event_argument.h" |
| 30 #include "build/build_config.h" | 30 #include "build/build_config.h" |
| 31 | 31 |
| 32 #if defined(OS_ANDROID) | 32 #if defined(OS_ANDROID) |
| 33 #include "base/trace_event/java_heap_dump_provider_android.h" | 33 #include "base/trace_event/java_heap_dump_provider_android.h" |
| 34 #endif | 34 #endif |
| 35 | 35 |
| 36 #if defined(OS_WIN) | 36 #if defined(OS_WIN) |
| 37 #include "base/trace_event/winheap_dump_provider_win.h" | 37 #include "base/trace_event/winheap_dump_provider_win.h" |
| 38 #endif | 38 #endif |
| 39 | 39 |
| 40 namespace base { | 40 namespace base { |
| 41 namespace trace_event { | 41 namespace trace_event { |
| 42 | 42 |
| 43 namespace { | 43 namespace { |
| 44 | 44 |
| 45 const int kTraceEventNumArgs = 1; | 45 const int kTraceEventNumArgs = 1; |
| 46 const char* kTraceEventArgNames[] = {"dumps"}; | 46 const char* kTraceEventArgNames[] = {"dumps"}; |
| 47 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; | 47 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; |
| 48 | 48 |
| 49 StaticAtomicSequenceNumber g_next_guid; | 49 StaticAtomicSequenceNumber g_next_guid; |
| 50 MemoryDumpManager* g_instance_for_testing = nullptr; | 50 MemoryDumpManager* g_instance_for_testing = nullptr; |
| 51 | 51 |
| 52 // The names of dump providers whitelisted for background tracing. Dump | |
| 53 // providers can be added here only if the background mode dump has very | |
| 54 // less performance and memory overhead. | |
| 55 const char* const kDumpProviderWhitelist[] = { | |
| 56 // TODO(ssid): Fill this list with dump provider names which support | |
| 57 // background mode, crbug.com/613198. | |
| 58 nullptr, // End of list marker. | |
| 59 }; | |
| 60 | |
| 61 // Callback wrapper to hook upon the completion of RequestGlobalDump() and | 52 // Callback wrapper to hook upon the completion of RequestGlobalDump() and |
| 62 // inject trace markers. | 53 // inject trace markers. |
| 63 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, | 54 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, |
| 64 uint64_t dump_guid, | 55 uint64_t dump_guid, |
| 65 bool success) { | 56 bool success) { |
| 66 TRACE_EVENT_NESTABLE_ASYNC_END1( | 57 TRACE_EVENT_NESTABLE_ASYNC_END1( |
| 67 MemoryDumpManager::kTraceCategory, "GlobalMemoryDump", | 58 MemoryDumpManager::kTraceCategory, "GlobalMemoryDump", |
| 68 TRACE_ID_MANGLE(dump_guid), "success", success); | 59 TRACE_ID_MANGLE(dump_guid), "success", success); |
| 69 | 60 |
| 70 if (!wrapped_callback.is_null()) { | 61 if (!wrapped_callback.is_null()) { |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 93 void EstimateTraceMemoryOverhead( | 84 void EstimateTraceMemoryOverhead( |
| 94 TraceEventMemoryOverhead* overhead) override { | 85 TraceEventMemoryOverhead* overhead) override { |
| 95 return (session_state.get()->*getter_function)() | 86 return (session_state.get()->*getter_function)() |
| 96 ->EstimateTraceMemoryOverhead(overhead); | 87 ->EstimateTraceMemoryOverhead(overhead); |
| 97 } | 88 } |
| 98 | 89 |
| 99 scoped_refptr<MemoryDumpSessionState> session_state; | 90 scoped_refptr<MemoryDumpSessionState> session_state; |
| 100 GetterFunctPtr const getter_function; | 91 GetterFunctPtr const getter_function; |
| 101 }; | 92 }; |
| 102 | 93 |
| 103 // Checks if the name is in the given |list|. Last element of the list should be | |
| 104 // an empty string. | |
| 105 bool IsNameInList(const char* name, const char* const* list) { | |
| 106 for (size_t i = 0; list[i] != nullptr; ++i) { | |
| 107 if (strcmp(name, list[i]) == 0) | |
| 108 return true; | |
| 109 } | |
| 110 return false; | |
| 111 } | |
| 112 | |
| 113 } // namespace | 94 } // namespace |
| 114 | 95 |
| 115 // static | 96 // static |
| 116 const char* const MemoryDumpManager::kTraceCategory = | 97 const char* const MemoryDumpManager::kTraceCategory = |
| 117 TRACE_DISABLED_BY_DEFAULT("memory-infra"); | 98 TRACE_DISABLED_BY_DEFAULT("memory-infra"); |
| 118 | 99 |
| 119 // static | 100 // static |
| 120 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; | 101 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; |
| 121 | 102 |
| 122 // static | 103 // static |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 143 | 124 |
| 144 // static | 125 // static |
| 145 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { | 126 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { |
| 146 g_instance_for_testing = instance; | 127 g_instance_for_testing = instance; |
| 147 } | 128 } |
| 148 | 129 |
| 149 MemoryDumpManager::MemoryDumpManager() | 130 MemoryDumpManager::MemoryDumpManager() |
| 150 : delegate_(nullptr), | 131 : delegate_(nullptr), |
| 151 is_coordinator_(false), | 132 is_coordinator_(false), |
| 152 memory_tracing_enabled_(0), | 133 memory_tracing_enabled_(0), |
| 153 dump_provider_whitelist_(kDumpProviderWhitelist), | |
| 154 tracing_process_id_(kInvalidTracingProcessId), | 134 tracing_process_id_(kInvalidTracingProcessId), |
| 155 dumper_registrations_ignored_for_testing_(false), | 135 dumper_registrations_ignored_for_testing_(false), |
| 156 heap_profiling_enabled_(false) { | 136 heap_profiling_enabled_(false) { |
| 157 g_next_guid.GetNext(); // Make sure that first guid is not zero. | 137 g_next_guid.GetNext(); // Make sure that first guid is not zero. |
| 158 | 138 |
| 159 // At this point the command line may not be initialized but we try to | 139 // At this point the command line may not be initialized but we try to |
| 160 // enable the heap profiler to capture allocations as soon as possible. | 140 // enable the heap profiler to capture allocations as soon as possible. |
| 161 EnableHeapProfilingIfNeeded(); | 141 EnableHeapProfilingIfNeeded(); |
| 162 } | 142 } |
| 163 | 143 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 267 } | 247 } |
| 268 | 248 |
| 269 void MemoryDumpManager::RegisterDumpProviderInternal( | 249 void MemoryDumpManager::RegisterDumpProviderInternal( |
| 270 MemoryDumpProvider* mdp, | 250 MemoryDumpProvider* mdp, |
| 271 const char* name, | 251 const char* name, |
| 272 scoped_refptr<SequencedTaskRunner> task_runner, | 252 scoped_refptr<SequencedTaskRunner> task_runner, |
| 273 const MemoryDumpProvider::Options& options) { | 253 const MemoryDumpProvider::Options& options) { |
| 274 if (dumper_registrations_ignored_for_testing_) | 254 if (dumper_registrations_ignored_for_testing_) |
| 275 return; | 255 return; |
| 276 | 256 |
| 277 bool whitelisted_for_background_mode = | 257 bool whitelisted_for_background_mode = IsMemoryDumpProviderWhitelisted(name); |
| 278 IsNameInList(name, dump_provider_whitelist_); | |
| 279 scoped_refptr<MemoryDumpProviderInfo> mdpinfo = | 258 scoped_refptr<MemoryDumpProviderInfo> mdpinfo = |
| 280 new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options, | 259 new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options, |
| 281 whitelisted_for_background_mode); | 260 whitelisted_for_background_mode); |
| 282 | 261 |
| 283 { | 262 { |
| 284 AutoLock lock(lock_); | 263 AutoLock lock(lock_); |
| 285 bool already_registered = !dump_providers_.insert(mdpinfo).second; | 264 bool already_registered = !dump_providers_.insert(mdpinfo).second; |
| 286 // This actually happens in some tests which don't have a clean tear-down | 265 // This actually happens in some tests which don't have a clean tear-down |
| 287 // path for RenderThreadImpl::Init(). | 266 // path for RenderThreadImpl::Init(). |
| 288 if (already_registered) | 267 if (already_registered) |
| (...skipping 265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 554 TRACE_EVENT_WITH_FLOW1(kTraceCategory, | 533 TRACE_EVENT_WITH_FLOW1(kTraceCategory, |
| 555 "MemoryDumpManager::InvokeOnMemoryDump", | 534 "MemoryDumpManager::InvokeOnMemoryDump", |
| 556 TRACE_ID_MANGLE(pmd_async_state->req_args.dump_guid), | 535 TRACE_ID_MANGLE(pmd_async_state->req_args.dump_guid), |
| 557 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, | 536 TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT, |
| 558 "dump_provider.name", mdpinfo->name); | 537 "dump_provider.name", mdpinfo->name); |
| 559 | 538 |
| 560 // Pid of the target process being dumped. Often kNullProcessId (= current | 539 // Pid of the target process being dumped. Often kNullProcessId (= current |
| 561 // process), non-zero when the coordinator process creates dumps on behalf | 540 // process), non-zero when the coordinator process creates dumps on behalf |
| 562 // of child processes (see crbug.com/461788). | 541 // of child processes (see crbug.com/461788). |
| 563 ProcessId target_pid = mdpinfo->options.target_pid; | 542 ProcessId target_pid = mdpinfo->options.target_pid; |
| 543 MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail}; | |
| 564 ProcessMemoryDump* pmd = | 544 ProcessMemoryDump* pmd = |
| 565 pmd_async_state->GetOrCreateMemoryDumpContainerForProcess(target_pid); | 545 pmd_async_state->GetOrCreateMemoryDumpContainerForProcess(target_pid, |
| 566 MemoryDumpArgs args = {pmd_async_state->req_args.level_of_detail}; | 546 args); |
| 567 bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd); | 547 bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd); |
| 568 mdpinfo->consecutive_failures = | 548 mdpinfo->consecutive_failures = |
| 569 dump_successful ? 0 : mdpinfo->consecutive_failures + 1; | 549 dump_successful ? 0 : mdpinfo->consecutive_failures + 1; |
| 570 } | 550 } |
| 571 | 551 |
| 572 pmd_async_state->pending_dump_providers.pop_back(); | 552 pmd_async_state->pending_dump_providers.pop_back(); |
| 573 SetupNextMemoryDump(std::move(pmd_async_state)); | 553 SetupNextMemoryDump(std::move(pmd_async_state)); |
| 574 } | 554 } |
| 575 | 555 |
| 576 // static | 556 // static |
| (...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 763 callback_task_runner(MessageLoop::current()->task_runner()), | 743 callback_task_runner(MessageLoop::current()->task_runner()), |
| 764 dump_thread_task_runner(std::move(dump_thread_task_runner)) { | 744 dump_thread_task_runner(std::move(dump_thread_task_runner)) { |
| 765 pending_dump_providers.reserve(dump_providers.size()); | 745 pending_dump_providers.reserve(dump_providers.size()); |
| 766 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); | 746 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); |
| 767 } | 747 } |
| 768 | 748 |
| 769 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { | 749 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { |
| 770 } | 750 } |
| 771 | 751 |
| 772 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: | 752 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: |
| 773 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) { | 753 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid, |
| 754 const MemoryDumpArgs& dump_args) { | |
| 774 auto iter = process_dumps.find(pid); | 755 auto iter = process_dumps.find(pid); |
| 775 if (iter == process_dumps.end()) { | 756 if (iter == process_dumps.end()) { |
| 776 std::unique_ptr<ProcessMemoryDump> new_pmd( | 757 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 777 new ProcessMemoryDump(session_state)); | 758 new ProcessMemoryDump(session_state, dump_args)); |
| 778 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 759 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 779 } | 760 } |
| 780 return iter->second.get(); | 761 return iter->second.get(); |
| 781 } | 762 } |
| 782 | 763 |
| 783 MemoryDumpManager::PeriodicGlobalDumpTimer::PeriodicGlobalDumpTimer() {} | 764 MemoryDumpManager::PeriodicGlobalDumpTimer::PeriodicGlobalDumpTimer() {} |
| 784 | 765 |
| 785 MemoryDumpManager::PeriodicGlobalDumpTimer::~PeriodicGlobalDumpTimer() { | 766 MemoryDumpManager::PeriodicGlobalDumpTimer::~PeriodicGlobalDumpTimer() { |
| 786 Stop(); | 767 Stop(); |
| 787 } | 768 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 839 if (heavy_dump_rate_ > 0 && periodic_dumps_count_ % heavy_dump_rate_ == 0) | 820 if (heavy_dump_rate_ > 0 && periodic_dumps_count_ % heavy_dump_rate_ == 0) |
| 840 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; | 821 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; |
| 841 ++periodic_dumps_count_; | 822 ++periodic_dumps_count_; |
| 842 | 823 |
| 843 MemoryDumpManager::GetInstance()->RequestGlobalDump( | 824 MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| 844 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | 825 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
| 845 } | 826 } |
| 846 | 827 |
| 847 } // namespace trace_event | 828 } // namespace trace_event |
| 848 } // namespace base | 829 } // namespace base |
| OLD | NEW |