| 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" |
| 19 #include "base/trace_event/heap_profiler.h" | 20 #include "base/trace_event/heap_profiler.h" |
| 20 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 21 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
| 21 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 22 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
| 22 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" | 23 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
| 23 #include "base/trace_event/malloc_dump_provider.h" | 24 #include "base/trace_event/malloc_dump_provider.h" |
| 24 #include "base/trace_event/memory_dump_provider.h" | 25 #include "base/trace_event/memory_dump_provider.h" |
| 25 #include "base/trace_event/memory_dump_session_state.h" | 26 #include "base/trace_event/memory_dump_session_state.h" |
| 26 #include "base/trace_event/process_memory_dump.h" | 27 #include "base/trace_event/process_memory_dump.h" |
| 27 #include "base/trace_event/trace_event.h" | 28 #include "base/trace_event/trace_event.h" |
| 28 #include "base/trace_event/trace_event_argument.h" | 29 #include "base/trace_event/trace_event_argument.h" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 39 namespace base { | 40 namespace base { |
| 40 namespace trace_event { | 41 namespace trace_event { |
| 41 | 42 |
| 42 namespace { | 43 namespace { |
| 43 | 44 |
| 44 const int kTraceEventNumArgs = 1; | 45 const int kTraceEventNumArgs = 1; |
| 45 const char* kTraceEventArgNames[] = {"dumps"}; | 46 const char* kTraceEventArgNames[] = {"dumps"}; |
| 46 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; | 47 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; |
| 47 | 48 |
| 48 StaticAtomicSequenceNumber g_next_guid; | 49 StaticAtomicSequenceNumber g_next_guid; |
| 49 uint32_t g_periodic_dumps_count = 0; | |
| 50 uint32_t g_heavy_dumps_rate = 0; | |
| 51 MemoryDumpManager* g_instance_for_testing = nullptr; | 50 MemoryDumpManager* g_instance_for_testing = nullptr; |
| 52 | 51 |
| 53 void RequestPeriodicGlobalDump() { | 52 // The names of dump providers whitelisted for background tracing. Dump |
| 54 MemoryDumpLevelOfDetail level_of_detail; | 53 // providers can be added here only if the background mode dump has very |
| 55 if (g_heavy_dumps_rate == 0) { | 54 // less performance and memory overhead. |
| 56 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; | 55 const char* const kDumpProviderWhitelist[] = { |
| 57 } else { | 56 // TODO(ssid): Fill this list with dump provider names which support |
| 58 level_of_detail = g_periodic_dumps_count == 0 | 57 // background mode, crbug.com/613198. |
| 59 ? MemoryDumpLevelOfDetail::DETAILED | 58 nullptr, // End of list marker. |
| 60 : MemoryDumpLevelOfDetail::LIGHT; | 59 }; |
| 61 | |
| 62 if (++g_periodic_dumps_count == g_heavy_dumps_rate) | |
| 63 g_periodic_dumps_count = 0; | |
| 64 } | |
| 65 | |
| 66 MemoryDumpManager::GetInstance()->RequestGlobalDump( | |
| 67 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | |
| 68 } | |
| 69 | 60 |
| 70 // Callback wrapper to hook upon the completion of RequestGlobalDump() and | 61 // Callback wrapper to hook upon the completion of RequestGlobalDump() and |
| 71 // inject trace markers. | 62 // inject trace markers. |
| 72 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, | 63 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, |
| 73 uint64_t dump_guid, | 64 uint64_t dump_guid, |
| 74 bool success) { | 65 bool success) { |
| 75 TRACE_EVENT_NESTABLE_ASYNC_END1( | 66 TRACE_EVENT_NESTABLE_ASYNC_END1( |
| 76 MemoryDumpManager::kTraceCategory, "GlobalMemoryDump", | 67 MemoryDumpManager::kTraceCategory, "GlobalMemoryDump", |
| 77 TRACE_ID_MANGLE(dump_guid), "success", success); | 68 TRACE_ID_MANGLE(dump_guid), "success", success); |
| 78 | 69 |
| (...skipping 23 matching lines...) Expand all Loading... |
| 102 void EstimateTraceMemoryOverhead( | 93 void EstimateTraceMemoryOverhead( |
| 103 TraceEventMemoryOverhead* overhead) override { | 94 TraceEventMemoryOverhead* overhead) override { |
| 104 return (session_state.get()->*getter_function)() | 95 return (session_state.get()->*getter_function)() |
| 105 ->EstimateTraceMemoryOverhead(overhead); | 96 ->EstimateTraceMemoryOverhead(overhead); |
| 106 } | 97 } |
| 107 | 98 |
| 108 scoped_refptr<MemoryDumpSessionState> session_state; | 99 scoped_refptr<MemoryDumpSessionState> session_state; |
| 109 GetterFunctPtr const getter_function; | 100 GetterFunctPtr const getter_function; |
| 110 }; | 101 }; |
| 111 | 102 |
| 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 |
| 112 } // namespace | 113 } // namespace |
| 113 | 114 |
| 114 // static | 115 // static |
| 115 const char* const MemoryDumpManager::kTraceCategory = | 116 const char* const MemoryDumpManager::kTraceCategory = |
| 116 TRACE_DISABLED_BY_DEFAULT("memory-infra"); | 117 TRACE_DISABLED_BY_DEFAULT("memory-infra"); |
| 117 | 118 |
| 118 // static | 119 // static |
| 119 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; | 120 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; |
| 120 | 121 |
| 121 // static | 122 // static |
| (...skipping 20 matching lines...) Expand all Loading... |
| 142 | 143 |
| 143 // static | 144 // static |
| 144 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { | 145 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { |
| 145 g_instance_for_testing = instance; | 146 g_instance_for_testing = instance; |
| 146 } | 147 } |
| 147 | 148 |
| 148 MemoryDumpManager::MemoryDumpManager() | 149 MemoryDumpManager::MemoryDumpManager() |
| 149 : delegate_(nullptr), | 150 : delegate_(nullptr), |
| 150 is_coordinator_(false), | 151 is_coordinator_(false), |
| 151 memory_tracing_enabled_(0), | 152 memory_tracing_enabled_(0), |
| 153 dump_provider_whitelist_(kDumpProviderWhitelist), |
| 152 tracing_process_id_(kInvalidTracingProcessId), | 154 tracing_process_id_(kInvalidTracingProcessId), |
| 153 dumper_registrations_ignored_for_testing_(false), | 155 dumper_registrations_ignored_for_testing_(false), |
| 154 heap_profiling_enabled_(false) { | 156 heap_profiling_enabled_(false) { |
| 155 g_next_guid.GetNext(); // Make sure that first guid is not zero. | 157 g_next_guid.GetNext(); // Make sure that first guid is not zero. |
| 156 | 158 |
| 157 // At this point the command line may not be initialized but we try to | 159 // At this point the command line may not be initialized but we try to |
| 158 // enable the heap profiler to capture allocations as soon as possible. | 160 // enable the heap profiler to capture allocations as soon as possible. |
| 159 EnableHeapProfilingIfNeeded(); | 161 EnableHeapProfilingIfNeeded(); |
| 160 } | 162 } |
| 161 | 163 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 265 } | 267 } |
| 266 | 268 |
| 267 void MemoryDumpManager::RegisterDumpProviderInternal( | 269 void MemoryDumpManager::RegisterDumpProviderInternal( |
| 268 MemoryDumpProvider* mdp, | 270 MemoryDumpProvider* mdp, |
| 269 const char* name, | 271 const char* name, |
| 270 scoped_refptr<SequencedTaskRunner> task_runner, | 272 scoped_refptr<SequencedTaskRunner> task_runner, |
| 271 const MemoryDumpProvider::Options& options) { | 273 const MemoryDumpProvider::Options& options) { |
| 272 if (dumper_registrations_ignored_for_testing_) | 274 if (dumper_registrations_ignored_for_testing_) |
| 273 return; | 275 return; |
| 274 | 276 |
| 277 bool whitelisted_for_background_mode = |
| 278 IsNameInList(name, dump_provider_whitelist_); |
| 275 scoped_refptr<MemoryDumpProviderInfo> mdpinfo = | 279 scoped_refptr<MemoryDumpProviderInfo> mdpinfo = |
| 276 new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options); | 280 new MemoryDumpProviderInfo(mdp, name, std::move(task_runner), options, |
| 281 whitelisted_for_background_mode); |
| 277 | 282 |
| 278 { | 283 { |
| 279 AutoLock lock(lock_); | 284 AutoLock lock(lock_); |
| 280 bool already_registered = !dump_providers_.insert(mdpinfo).second; | 285 bool already_registered = !dump_providers_.insert(mdpinfo).second; |
| 281 // This actually happens in some tests which don't have a clean tear-down | 286 // This actually happens in some tests which don't have a clean tear-down |
| 282 // path for RenderThreadImpl::Init(). | 287 // path for RenderThreadImpl::Init(). |
| 283 if (already_registered) | 288 if (already_registered) |
| 284 return; | 289 return; |
| 285 } | 290 } |
| 286 | 291 |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 442 pmd_async_state->pending_dump_providers.clear(); | 447 pmd_async_state->pending_dump_providers.clear(); |
| 443 } | 448 } |
| 444 if (pmd_async_state->pending_dump_providers.empty()) | 449 if (pmd_async_state->pending_dump_providers.empty()) |
| 445 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); | 450 return FinalizeDumpAndAddToTrace(std::move(pmd_async_state)); |
| 446 | 451 |
| 447 // Read MemoryDumpProviderInfo thread safety considerations in | 452 // Read MemoryDumpProviderInfo thread safety considerations in |
| 448 // memory_dump_manager.h when accessing |mdpinfo| fields. | 453 // memory_dump_manager.h when accessing |mdpinfo| fields. |
| 449 MemoryDumpProviderInfo* mdpinfo = | 454 MemoryDumpProviderInfo* mdpinfo = |
| 450 pmd_async_state->pending_dump_providers.back().get(); | 455 pmd_async_state->pending_dump_providers.back().get(); |
| 451 | 456 |
| 457 // If we are in background tracing, we should invoke only the whitelisted |
| 458 // providers. Ignore other providers and continue. |
| 459 if (pmd_async_state->req_args.level_of_detail == |
| 460 MemoryDumpLevelOfDetail::BACKGROUND && |
| 461 !mdpinfo->whitelisted_for_background_mode) { |
| 462 pmd_async_state->pending_dump_providers.pop_back(); |
| 463 return SetupNextMemoryDump(std::move(pmd_async_state)); |
| 464 } |
| 465 |
| 452 // If the dump provider did not specify a task runner affinity, dump on | 466 // If the dump provider did not specify a task runner affinity, dump on |
| 453 // |dump_thread_| which is already checked above for presence. | 467 // |dump_thread_| which is already checked above for presence. |
| 454 SequencedTaskRunner* task_runner = mdpinfo->task_runner.get(); | 468 SequencedTaskRunner* task_runner = mdpinfo->task_runner.get(); |
| 455 if (!task_runner) { | 469 if (!task_runner) { |
| 456 DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner); | 470 DCHECK(mdpinfo->options.dumps_on_single_thread_task_runner); |
| 457 task_runner = pmd_async_state->dump_thread_task_runner.get(); | 471 task_runner = pmd_async_state->dump_thread_task_runner.get(); |
| 458 DCHECK(task_runner); | 472 DCHECK(task_runner); |
| 459 } | 473 } |
| 460 | 474 |
| 461 if (mdpinfo->options.dumps_on_single_thread_task_runner && | 475 if (mdpinfo->options.dumps_on_single_thread_task_runner && |
| (...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 625 // while the |lock_| is taken; | 639 // while the |lock_| is taken; |
| 626 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); | 640 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); |
| 627 | 641 |
| 628 // Spin-up the thread used to invoke unbound dump providers. | 642 // Spin-up the thread used to invoke unbound dump providers. |
| 629 std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra")); | 643 std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra")); |
| 630 if (!dump_thread->Start()) { | 644 if (!dump_thread->Start()) { |
| 631 LOG(ERROR) << "Failed to start the memory-infra thread for tracing"; | 645 LOG(ERROR) << "Failed to start the memory-infra thread for tracing"; |
| 632 return; | 646 return; |
| 633 } | 647 } |
| 634 | 648 |
| 635 AutoLock lock(lock_); | 649 const TraceConfig trace_config = |
| 636 | 650 TraceLog::GetInstance()->GetCurrentTraceConfig(); |
| 637 DCHECK(delegate_); // At this point we must have a delegate. | 651 scoped_refptr<MemoryDumpSessionState> session_state = |
| 638 session_state_ = new MemoryDumpSessionState; | 652 new MemoryDumpSessionState; |
| 639 | 653 session_state->SetMemoryDumpConfig(trace_config.memory_dump_config()); |
| 640 if (heap_profiling_enabled_) { | 654 if (heap_profiling_enabled_) { |
| 641 // If heap profiling is enabled, the stack frame deduplicator and type name | 655 // If heap profiling is enabled, the stack frame deduplicator and type name |
| 642 // deduplicator will be in use. Add a metadata events to write the frames | 656 // deduplicator will be in use. Add a metadata events to write the frames |
| 643 // and type IDs. | 657 // and type IDs. |
| 644 session_state_->SetStackFrameDeduplicator( | 658 session_state->SetStackFrameDeduplicator( |
| 645 WrapUnique(new StackFrameDeduplicator)); | 659 WrapUnique(new StackFrameDeduplicator)); |
| 646 | 660 |
| 647 session_state_->SetTypeNameDeduplicator( | 661 session_state->SetTypeNameDeduplicator( |
| 648 WrapUnique(new TypeNameDeduplicator)); | 662 WrapUnique(new TypeNameDeduplicator)); |
| 649 | 663 |
| 650 TRACE_EVENT_API_ADD_METADATA_EVENT( | 664 TRACE_EVENT_API_ADD_METADATA_EVENT( |
| 651 TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames", | 665 TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames", |
| 652 "stackFrames", | 666 "stackFrames", |
| 653 WrapUnique( | 667 WrapUnique(new SessionStateConvertableProxy<StackFrameDeduplicator>( |
| 654 new SessionStateConvertableProxy<StackFrameDeduplicator>( | 668 session_state, &MemoryDumpSessionState::stack_frame_deduplicator))); |
| 655 session_state_, | |
| 656 &MemoryDumpSessionState::stack_frame_deduplicator))); | |
| 657 | 669 |
| 658 TRACE_EVENT_API_ADD_METADATA_EVENT( | 670 TRACE_EVENT_API_ADD_METADATA_EVENT( |
| 659 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", | 671 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", |
| 660 "typeNames", | 672 "typeNames", |
| 661 WrapUnique(new SessionStateConvertableProxy<TypeNameDeduplicator>( | 673 WrapUnique(new SessionStateConvertableProxy<TypeNameDeduplicator>( |
| 662 session_state_, &MemoryDumpSessionState::type_name_deduplicator))); | 674 session_state, &MemoryDumpSessionState::type_name_deduplicator))); |
| 663 } | 675 } |
| 664 | 676 |
| 665 DCHECK(!dump_thread_); | 677 { |
| 666 dump_thread_ = std::move(dump_thread); | 678 AutoLock lock(lock_); |
| 667 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | |
| 668 | 679 |
| 669 // TODO(primiano): This is a temporary hack to disable periodic memory dumps | 680 DCHECK(delegate_); // At this point we must have a delegate. |
| 670 // when running memory benchmarks until telemetry uses TraceConfig to | 681 session_state_ = session_state; |
| 671 // enable/disable periodic dumps. See crbug.com/529184 . | 682 |
| 672 if (!is_coordinator_ || | 683 DCHECK(!dump_thread_); |
| 673 CommandLine::ForCurrentProcess()->HasSwitch( | 684 dump_thread_ = std::move(dump_thread); |
| 674 "enable-memory-benchmarking")) { | 685 |
| 675 return; | 686 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
| 687 |
| 688 // TODO(primiano): This is a temporary hack to disable periodic memory dumps |
| 689 // when running memory benchmarks until telemetry uses TraceConfig to |
| 690 // enable/disable periodic dumps. See crbug.com/529184 . |
| 691 if (!is_coordinator_ || |
| 692 CommandLine::ForCurrentProcess()->HasSwitch( |
| 693 "enable-memory-benchmarking")) { |
| 694 return; |
| 695 } |
| 676 } | 696 } |
| 677 | 697 |
| 678 // Enable periodic dumps. At the moment the periodic support is limited to at | 698 // Enable periodic dumps if necessary. |
| 679 // most one low-detail periodic dump and at most one high-detail periodic | 699 periodic_dump_timer_.Start(trace_config.memory_dump_config().triggers); |
| 680 // dump. If both are specified the high-detail period must be an integer | |
| 681 // multiple of the low-level one. | |
| 682 g_periodic_dumps_count = 0; | |
| 683 const TraceConfig trace_config = | |
| 684 TraceLog::GetInstance()->GetCurrentTraceConfig(); | |
| 685 session_state_->SetMemoryDumpConfig(trace_config.memory_dump_config()); | |
| 686 const std::vector<TraceConfig::MemoryDumpConfig::Trigger>& triggers_list = | |
| 687 trace_config.memory_dump_config().triggers; | |
| 688 if (triggers_list.empty()) | |
| 689 return; | |
| 690 | |
| 691 uint32_t min_timer_period_ms = std::numeric_limits<uint32_t>::max(); | |
| 692 uint32_t heavy_dump_period_ms = 0; | |
| 693 DCHECK_LE(triggers_list.size(), 2u); | |
| 694 for (const TraceConfig::MemoryDumpConfig::Trigger& config : triggers_list) { | |
| 695 DCHECK(config.periodic_interval_ms); | |
| 696 if (config.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) | |
| 697 heavy_dump_period_ms = config.periodic_interval_ms; | |
| 698 min_timer_period_ms = | |
| 699 std::min(min_timer_period_ms, config.periodic_interval_ms); | |
| 700 } | |
| 701 DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms); | |
| 702 g_heavy_dumps_rate = heavy_dump_period_ms / min_timer_period_ms; | |
| 703 | |
| 704 periodic_dump_timer_.Start(FROM_HERE, | |
| 705 TimeDelta::FromMilliseconds(min_timer_period_ms), | |
| 706 base::Bind(&RequestPeriodicGlobalDump)); | |
| 707 } | 700 } |
| 708 | 701 |
| 709 void MemoryDumpManager::OnTraceLogDisabled() { | 702 void MemoryDumpManager::OnTraceLogDisabled() { |
| 710 // There might be a memory dump in progress while this happens. Therefore, | 703 // There might be a memory dump in progress while this happens. Therefore, |
| 711 // ensure that the MDM state which depends on the tracing enabled / disabled | 704 // ensure that the MDM state which depends on the tracing enabled / disabled |
| 712 // state is always accessed by the dumping methods holding the |lock_|. | 705 // state is always accessed by the dumping methods holding the |lock_|. |
| 713 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 706 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
| 714 std::unique_ptr<Thread> dump_thread; | 707 std::unique_ptr<Thread> dump_thread; |
| 715 { | 708 { |
| 716 AutoLock lock(lock_); | 709 AutoLock lock(lock_); |
| 717 dump_thread = std::move(dump_thread_); | 710 dump_thread = std::move(dump_thread_); |
| 718 session_state_ = nullptr; | 711 session_state_ = nullptr; |
| 719 } | 712 } |
| 720 | 713 |
| 721 // Thread stops are blocking and must be performed outside of the |lock_| | 714 // Thread stops are blocking and must be performed outside of the |lock_| |
| 722 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). | 715 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). |
| 723 periodic_dump_timer_.Stop(); | 716 periodic_dump_timer_.Stop(); |
| 724 if (dump_thread) | 717 if (dump_thread) |
| 725 dump_thread->Stop(); | 718 dump_thread->Stop(); |
| 726 } | 719 } |
| 727 | 720 |
| 728 uint64_t MemoryDumpManager::GetTracingProcessId() const { | 721 uint64_t MemoryDumpManager::GetTracingProcessId() const { |
| 729 return delegate_->GetTracingProcessId(); | 722 return delegate_->GetTracingProcessId(); |
| 730 } | 723 } |
| 731 | 724 |
| 732 MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo( | 725 MemoryDumpManager::MemoryDumpProviderInfo::MemoryDumpProviderInfo( |
| 733 MemoryDumpProvider* dump_provider, | 726 MemoryDumpProvider* dump_provider, |
| 734 const char* name, | 727 const char* name, |
| 735 scoped_refptr<SequencedTaskRunner> task_runner, | 728 scoped_refptr<SequencedTaskRunner> task_runner, |
| 736 const MemoryDumpProvider::Options& options) | 729 const MemoryDumpProvider::Options& options, |
| 730 bool whitelisted_for_background_mode) |
| 737 : dump_provider(dump_provider), | 731 : dump_provider(dump_provider), |
| 738 name(name), | 732 name(name), |
| 739 task_runner(std::move(task_runner)), | 733 task_runner(std::move(task_runner)), |
| 740 options(options), | 734 options(options), |
| 741 consecutive_failures(0), | 735 consecutive_failures(0), |
| 742 disabled(false) {} | 736 disabled(false), |
| 737 whitelisted_for_background_mode(whitelisted_for_background_mode) {} |
| 743 | 738 |
| 744 MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {} | 739 MemoryDumpManager::MemoryDumpProviderInfo::~MemoryDumpProviderInfo() {} |
| 745 | 740 |
| 746 bool MemoryDumpManager::MemoryDumpProviderInfo::Comparator::operator()( | 741 bool MemoryDumpManager::MemoryDumpProviderInfo::Comparator::operator()( |
| 747 const scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo>& a, | 742 const scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo>& a, |
| 748 const scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo>& b) const { | 743 const scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo>& b) const { |
| 749 if (!a || !b) | 744 if (!a || !b) |
| 750 return a.get() < b.get(); | 745 return a.get() < b.get(); |
| 751 // Ensure that unbound providers (task_runner == nullptr) always run last. | 746 // Ensure that unbound providers (task_runner == nullptr) always run last. |
| 752 // Rationale: some unbound dump providers are known to be slow, keep them last | 747 // Rationale: some unbound dump providers are known to be slow, keep them last |
| (...skipping 25 matching lines...) Expand all Loading... |
| 778 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) { | 773 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid) { |
| 779 auto iter = process_dumps.find(pid); | 774 auto iter = process_dumps.find(pid); |
| 780 if (iter == process_dumps.end()) { | 775 if (iter == process_dumps.end()) { |
| 781 std::unique_ptr<ProcessMemoryDump> new_pmd( | 776 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 782 new ProcessMemoryDump(session_state)); | 777 new ProcessMemoryDump(session_state)); |
| 783 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 778 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 784 } | 779 } |
| 785 return iter->second.get(); | 780 return iter->second.get(); |
| 786 } | 781 } |
| 787 | 782 |
| 783 MemoryDumpManager::PeriodicGlobalDumpTimer::PeriodicGlobalDumpTimer() {} |
| 784 |
| 785 MemoryDumpManager::PeriodicGlobalDumpTimer::~PeriodicGlobalDumpTimer() { |
| 786 Stop(); |
| 787 } |
| 788 |
| 789 void MemoryDumpManager::PeriodicGlobalDumpTimer::Start( |
| 790 const std::vector<TraceConfig::MemoryDumpConfig::Trigger>& triggers_list) { |
| 791 if (triggers_list.empty()) |
| 792 return; |
| 793 |
| 794 // At the moment the periodic support is limited to at most one periodic |
| 795 // trigger per dump mode. All intervals should be an integer multiple of the |
| 796 // smallest interval specified. |
| 797 periodic_dumps_count_ = 0; |
| 798 uint32_t min_timer_period_ms = std::numeric_limits<uint32_t>::max(); |
| 799 uint32_t light_dump_period_ms = 0; |
| 800 uint32_t heavy_dump_period_ms = 0; |
| 801 DCHECK_LE(triggers_list.size(), 3u); |
| 802 for (const TraceConfig::MemoryDumpConfig::Trigger& config : triggers_list) { |
| 803 DCHECK_NE(0u, config.periodic_interval_ms); |
| 804 if (config.level_of_detail == MemoryDumpLevelOfDetail::LIGHT) { |
| 805 DCHECK_EQ(0u, light_dump_period_ms); |
| 806 light_dump_period_ms = config.periodic_interval_ms; |
| 807 } else if (config.level_of_detail == MemoryDumpLevelOfDetail::DETAILED) { |
| 808 DCHECK_EQ(0u, heavy_dump_period_ms); |
| 809 heavy_dump_period_ms = config.periodic_interval_ms; |
| 810 } |
| 811 min_timer_period_ms = |
| 812 std::min(min_timer_period_ms, config.periodic_interval_ms); |
| 813 } |
| 814 |
| 815 DCHECK_EQ(0u, light_dump_period_ms % min_timer_period_ms); |
| 816 light_dump_rate_ = light_dump_period_ms / min_timer_period_ms; |
| 817 DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms); |
| 818 heavy_dump_rate_ = heavy_dump_period_ms / min_timer_period_ms; |
| 819 |
| 820 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(min_timer_period_ms), |
| 821 base::Bind(&PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump, |
| 822 base::Unretained(this))); |
| 823 } |
| 824 |
| 825 void MemoryDumpManager::PeriodicGlobalDumpTimer::Stop() { |
| 826 if (IsRunning()) { |
| 827 timer_.Stop(); |
| 828 } |
| 829 } |
| 830 |
| 831 bool MemoryDumpManager::PeriodicGlobalDumpTimer::IsRunning() { |
| 832 return timer_.IsRunning(); |
| 833 } |
| 834 |
| 835 void MemoryDumpManager::PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump() { |
| 836 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; |
| 837 if (light_dump_rate_ > 0 && periodic_dumps_count_ % light_dump_rate_ == 0) |
| 838 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; |
| 839 if (heavy_dump_rate_ > 0 && periodic_dumps_count_ % heavy_dump_rate_ == 0) |
| 840 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; |
| 841 ++periodic_dumps_count_; |
| 842 |
| 843 MemoryDumpManager::GetInstance()->RequestGlobalDump( |
| 844 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
| 845 } |
| 846 |
| 788 } // namespace trace_event | 847 } // namespace trace_event |
| 789 } // namespace base | 848 } // namespace base |
| OLD | NEW |