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/allocator/features.h" | 10 #include "base/allocator/features.h" |
11 #include "base/atomic_sequence_num.h" | 11 #include "base/atomic_sequence_num.h" |
12 #include "base/base_switches.h" | 12 #include "base/base_switches.h" |
13 #include "base/command_line.h" | 13 #include "base/command_line.h" |
14 #include "base/compiler_specific.h" | 14 #include "base/compiler_specific.h" |
15 #include "base/debug/debugging_flags.h" | 15 #include "base/debug/debugging_flags.h" |
16 #include "base/debug/stack_trace.h" | 16 #include "base/debug/stack_trace.h" |
17 #include "base/memory/ptr_util.h" | 17 #include "base/memory/ptr_util.h" |
18 #include "base/threading/thread.h" | 18 #include "base/threading/thread.h" |
19 #include "base/threading/thread_task_runner_handle.h" | 19 #include "base/threading/thread_task_runner_handle.h" |
20 #include "base/trace_event/heap_profiler.h" | 20 #include "base/trace_event/heap_profiler.h" |
21 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 21 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
22 #include "base/trace_event/heap_profiler_event_filter.h" | 22 #include "base/trace_event/heap_profiler_event_filter.h" |
23 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 23 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
24 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" | 24 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
25 #include "base/trace_event/malloc_dump_provider.h" | 25 #include "base/trace_event/malloc_dump_provider.h" |
26 #include "base/trace_event/memory_dump_provider.h" | 26 #include "base/trace_event/memory_dump_provider.h" |
27 #include "base/trace_event/memory_dump_session_state.h" | 27 #include "base/trace_event/memory_dump_session_state.h" |
28 #include "base/trace_event/memory_dump_trigger.h" | |
28 #include "base/trace_event/memory_infra_background_whitelist.h" | 29 #include "base/trace_event/memory_infra_background_whitelist.h" |
29 #include "base/trace_event/process_memory_dump.h" | 30 #include "base/trace_event/process_memory_dump.h" |
30 #include "base/trace_event/trace_event.h" | 31 #include "base/trace_event/trace_event.h" |
31 #include "base/trace_event/trace_event_argument.h" | 32 #include "base/trace_event/trace_event_argument.h" |
32 #include "build/build_config.h" | 33 #include "build/build_config.h" |
33 | 34 |
34 #if defined(OS_ANDROID) | 35 #if defined(OS_ANDROID) |
35 #include "base/trace_event/java_heap_dump_provider_android.h" | 36 #include "base/trace_event/java_heap_dump_provider_android.h" |
36 #endif | 37 #endif |
37 | 38 |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
121 LeakySingletonTraits<MemoryDumpManager>>::get(); | 122 LeakySingletonTraits<MemoryDumpManager>>::get(); |
122 } | 123 } |
123 | 124 |
124 // static | 125 // static |
125 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { | 126 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { |
126 g_instance_for_testing = instance; | 127 g_instance_for_testing = instance; |
127 } | 128 } |
128 | 129 |
129 MemoryDumpManager::MemoryDumpManager() | 130 MemoryDumpManager::MemoryDumpManager() |
130 : delegate_(nullptr), | 131 : delegate_(nullptr), |
131 is_coordinator_(false), | |
132 memory_tracing_enabled_(0), | 132 memory_tracing_enabled_(0), |
133 tracing_process_id_(kInvalidTracingProcessId), | 133 tracing_process_id_(kInvalidTracingProcessId), |
134 dumper_registrations_ignored_for_testing_(false), | 134 dumper_registrations_ignored_for_testing_(false), |
135 heap_profiling_enabled_(false) { | 135 heap_profiling_enabled_(false) { |
136 g_next_guid.GetNext(); // Make sure that first guid is not zero. | 136 g_next_guid.GetNext(); // Make sure that first guid is not zero. |
137 | 137 |
138 // At this point the command line may not be initialized but we try to | 138 // At this point the command line may not be initialized but we try to |
139 // enable the heap profiler to capture allocations as soon as possible. | 139 // enable the heap profiler to capture allocations as soon as possible. |
140 EnableHeapProfilingIfNeeded(); | 140 EnableHeapProfilingIfNeeded(); |
141 } | 141 } |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
181 heap_profiling_enabled_ = true; | 181 heap_profiling_enabled_ = true; |
182 } | 182 } |
183 | 183 |
184 void MemoryDumpManager::Initialize(MemoryDumpManagerDelegate* delegate, | 184 void MemoryDumpManager::Initialize(MemoryDumpManagerDelegate* delegate, |
185 bool is_coordinator) { | 185 bool is_coordinator) { |
186 { | 186 { |
187 AutoLock lock(lock_); | 187 AutoLock lock(lock_); |
188 DCHECK(delegate); | 188 DCHECK(delegate); |
189 DCHECK(!delegate_); | 189 DCHECK(!delegate_); |
190 delegate_ = delegate; | 190 delegate_ = delegate; |
191 is_coordinator_ = is_coordinator; | |
192 EnableHeapProfilingIfNeeded(); | 191 EnableHeapProfilingIfNeeded(); |
192 dump_trigger_.reset(new MemoryDumpTrigger(this, is_coordinator)); | |
193 } | 193 } |
194 | 194 |
195 // Enable the core dump providers. | 195 // Enable the core dump providers. |
196 #if defined(MALLOC_MEMORY_TRACING_SUPPORTED) | 196 #if defined(MALLOC_MEMORY_TRACING_SUPPORTED) |
197 RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr); | 197 RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr); |
198 #endif | 198 #endif |
199 | 199 |
200 #if defined(OS_ANDROID) | 200 #if defined(OS_ANDROID) |
201 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap", | 201 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap", |
202 nullptr); | 202 nullptr); |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
367 // destroyed by the caller soon after this method returns. | 367 // destroyed by the caller soon after this method returns. |
368 (*mdp_iter)->disabled = true; | 368 (*mdp_iter)->disabled = true; |
369 dump_providers_.erase(mdp_iter); | 369 dump_providers_.erase(mdp_iter); |
370 } | 370 } |
371 | 371 |
372 void MemoryDumpManager::RegisterPollingMDPOnDumpThread( | 372 void MemoryDumpManager::RegisterPollingMDPOnDumpThread( |
373 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { | 373 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { |
374 DCHECK(!mdpinfo->task_runner); | 374 DCHECK(!mdpinfo->task_runner); |
375 AutoLock lock(lock_); | 375 AutoLock lock(lock_); |
376 dump_providers_for_polling_.insert(mdpinfo); | 376 dump_providers_for_polling_.insert(mdpinfo); |
377 | |
378 // Setup polling when first polling supported provider is registered since | |
379 // OnTraceLogEnabled() would not have setup polling without any provider that | |
380 // supports polling. | |
Primiano Tucci (use gerrit)
2017/01/18 16:16:06
can you expand a bit here about why? To me feels a
ssid
2017/01/20 23:07:27
If I did that then we would be unnecessarily setti
| |
381 if (dump_providers_for_polling_.size() == 1) { | |
382 dump_trigger_->SetupPeakTriggers( | |
383 session_state_->memory_dump_config().triggers, | |
384 ThreadTaskRunnerHandle::Get()); | |
Primiano Tucci (use gerrit)
2017/01/18 16:16:06
this one confuses me a bit: how do you know at thi
ssid
2017/01/20 23:07:27
So, now it does not matter. The scheduler knows if
| |
385 } | |
377 } | 386 } |
378 | 387 |
379 void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( | 388 void MemoryDumpManager::UnregisterPollingMDPOnDumpThread( |
380 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { | 389 scoped_refptr<MemoryDumpManager::MemoryDumpProviderInfo> mdpinfo) { |
381 mdpinfo->dump_provider->SuspendFastMemoryPolling(); | 390 mdpinfo->dump_provider->SuspendFastMemoryPolling(); |
382 | 391 |
383 AutoLock lock(lock_); | 392 AutoLock lock(lock_); |
384 dump_providers_for_polling_.erase(mdpinfo); | 393 dump_providers_for_polling_.erase(mdpinfo); |
394 DCHECK(!dump_providers_for_polling_.empty()) | |
395 << "All polling MDPs cannot be unregistered, since it will cause polling " | |
396 "without without any MDPs"; | |
385 } | 397 } |
386 | 398 |
387 void MemoryDumpManager::RequestGlobalDump( | 399 void MemoryDumpManager::RequestGlobalDump( |
388 MemoryDumpType dump_type, | 400 MemoryDumpType dump_type, |
389 MemoryDumpLevelOfDetail level_of_detail, | 401 MemoryDumpLevelOfDetail level_of_detail, |
390 const MemoryDumpCallback& callback) { | 402 const MemoryDumpCallback& callback) { |
391 // Bail out immediately if tracing is not enabled at all or if the dump mode | 403 // Bail out immediately if tracing is not enabled at all or if the dump mode |
392 // is not allowed. | 404 // is not allowed. |
393 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) || | 405 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) || |
394 !IsDumpModeAllowed(level_of_detail)) { | 406 !IsDumpModeAllowed(level_of_detail)) { |
(...skipping 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
630 args); | 642 args); |
631 bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd); | 643 bool dump_successful = mdpinfo->dump_provider->OnMemoryDump(args, pmd); |
632 mdpinfo->consecutive_failures = | 644 mdpinfo->consecutive_failures = |
633 dump_successful ? 0 : mdpinfo->consecutive_failures + 1; | 645 dump_successful ? 0 : mdpinfo->consecutive_failures + 1; |
634 } | 646 } |
635 | 647 |
636 pmd_async_state->pending_dump_providers.pop_back(); | 648 pmd_async_state->pending_dump_providers.pop_back(); |
637 SetupNextMemoryDump(std::move(pmd_async_state)); | 649 SetupNextMemoryDump(std::move(pmd_async_state)); |
638 } | 650 } |
639 | 651 |
640 void MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) { | 652 bool MemoryDumpManager::PollFastMemoryTotal(uint64_t* memory_total) { |
653 #if DCHECK_IS_ON() | |
654 { | |
655 AutoLock lock(lock_); | |
656 if (dump_thread_) | |
657 DCHECK(dump_thread_->task_runner()->BelongsToCurrentThread()); | |
658 } | |
659 #endif | |
660 if (dump_providers_for_polling_.empty()) | |
661 return false; | |
662 | |
641 *memory_total = 0; | 663 *memory_total = 0; |
642 // Note that we call PollFastMemoryTotal() even if the dump provider is | 664 // Note that we call PollFastMemoryTotal() even if the dump provider is |
643 // disabled (unregistered). This is to avoid taking lock while polling. | 665 // disabled (unregistered). This is to avoid taking lock while polling. |
644 for (const auto& mdpinfo : dump_providers_for_polling_) { | 666 for (const auto& mdpinfo : dump_providers_for_polling_) { |
645 uint64_t value = 0; | 667 uint64_t value = 0; |
646 mdpinfo->dump_provider->PollFastMemoryTotal(&value); | 668 mdpinfo->dump_provider->PollFastMemoryTotal(&value); |
647 *memory_total += value; | 669 *memory_total += value; |
648 } | 670 } |
649 return; | 671 return true; |
650 } | 672 } |
651 | 673 |
652 // static | 674 // static |
653 void MemoryDumpManager::FinalizeDumpAndAddToTrace( | 675 void MemoryDumpManager::FinalizeDumpAndAddToTrace( |
654 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { | 676 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { |
655 HEAP_PROFILER_SCOPED_IGNORE; | 677 HEAP_PROFILER_SCOPED_IGNORE; |
656 DCHECK(pmd_async_state->pending_dump_providers.empty()); | 678 DCHECK(pmd_async_state->pending_dump_providers.empty()); |
657 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; | 679 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; |
658 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { | 680 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { |
659 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 681 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
746 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( | 768 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( |
747 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); | 769 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); |
748 | 770 |
749 TRACE_EVENT_API_ADD_METADATA_EVENT( | 771 TRACE_EVENT_API_ADD_METADATA_EVENT( |
750 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", | 772 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", |
751 "typeNames", | 773 "typeNames", |
752 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( | 774 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( |
753 session_state, &MemoryDumpSessionState::type_name_deduplicator)); | 775 session_state, &MemoryDumpSessionState::type_name_deduplicator)); |
754 } | 776 } |
755 | 777 |
778 scoped_refptr<SingleThreadTaskRunner> polling_task_runner; | |
779 MemoryDumpTrigger* trigger = nullptr; | |
756 { | 780 { |
757 AutoLock lock(lock_); | 781 AutoLock lock(lock_); |
758 | 782 |
759 DCHECK(delegate_); // At this point we must have a delegate. | 783 DCHECK(delegate_); // At this point we must have a delegate. |
760 session_state_ = session_state; | 784 session_state_ = session_state; |
761 | 785 |
762 DCHECK(!dump_thread_); | 786 DCHECK(!dump_thread_); |
763 dump_thread_ = std::move(dump_thread); | 787 dump_thread_ = std::move(dump_thread); |
764 | 788 |
765 dump_providers_for_polling_.clear(); | 789 dump_providers_for_polling_.clear(); |
766 for (const auto& mdpinfo : dump_providers_) { | 790 for (const auto& mdpinfo : dump_providers_) { |
767 if (mdpinfo->options.is_fast_polling_supported) | 791 if (mdpinfo->options.is_fast_polling_supported) |
768 dump_providers_for_polling_.insert(mdpinfo); | 792 dump_providers_for_polling_.insert(mdpinfo); |
769 } | 793 } |
794 if (!dump_providers_for_polling_.empty()) | |
795 polling_task_runner = dump_thread_->task_runner(); | |
770 | 796 |
771 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | 797 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
772 | 798 |
773 // TODO(primiano): This is a temporary hack to disable periodic memory dumps | 799 trigger = dump_trigger_.get(); |
774 // when running memory benchmarks until telemetry uses TraceConfig to | |
775 // enable/disable periodic dumps. See crbug.com/529184 . | |
776 if (!is_coordinator_ || | |
777 CommandLine::ForCurrentProcess()->HasSwitch( | |
778 "enable-memory-benchmarking")) { | |
779 return; | |
780 } | |
781 } | 800 } |
782 | 801 |
802 // Setup peak triggers only if some polling supported provider was registered, | |
803 // else polling will be setup by RegisterPollingMDPOnDumpThread when first | |
804 // polling MDP registers. | |
805 if (polling_task_runner) { | |
806 trigger->SetupPeakTriggers(trace_config.memory_dump_config().triggers, | |
807 polling_task_runner); | |
808 } | |
783 // Enable periodic dumps if necessary. | 809 // Enable periodic dumps if necessary. |
784 periodic_dump_timer_.Start(trace_config.memory_dump_config().triggers); | 810 trigger->SetupPeriodicTriggers(trace_config.memory_dump_config().triggers); |
785 } | 811 } |
786 | 812 |
787 void MemoryDumpManager::OnTraceLogDisabled() { | 813 void MemoryDumpManager::OnTraceLogDisabled() { |
788 // There might be a memory dump in progress while this happens. Therefore, | 814 // There might be a memory dump in progress while this happens. Therefore, |
789 // ensure that the MDM state which depends on the tracing enabled / disabled | 815 // ensure that the MDM state which depends on the tracing enabled / disabled |
790 // state is always accessed by the dumping methods holding the |lock_|. | 816 // state is always accessed by the dumping methods holding the |lock_|. |
791 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) | 817 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) |
792 return; | 818 return; |
793 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 819 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
794 std::unique_ptr<Thread> dump_thread; | 820 std::unique_ptr<Thread> dump_thread; |
795 { | 821 { |
796 AutoLock lock(lock_); | 822 AutoLock lock(lock_); |
797 dump_thread = std::move(dump_thread_); | 823 dump_thread = std::move(dump_thread_); |
798 session_state_ = nullptr; | 824 session_state_ = nullptr; |
799 } | 825 } |
800 | 826 |
801 // Thread stops are blocking and must be performed outside of the |lock_| | 827 // Thread stops are blocking and must be performed outside of the |lock_| |
802 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). | 828 // or will deadlock (e.g., if SetupNextMemoryDump() tries to acquire it). |
803 periodic_dump_timer_.Stop(); | |
804 if (dump_thread) | 829 if (dump_thread) |
805 dump_thread->Stop(); | 830 dump_thread->Stop(); |
806 | 831 |
807 // |dump_providers_for_polling_| must be cleared only after the dump thread is | 832 // |dump_providers_for_polling_| must be cleared and triggers must be |
808 // stopped (polling tasks are done). | 833 // disabled only after the dump thread is stopped (polling tasks are done). |
834 MemoryDumpTrigger* trigger = nullptr; | |
809 { | 835 { |
810 AutoLock lock(lock_); | 836 AutoLock lock(lock_); |
811 for (const auto& mdpinfo : dump_providers_for_polling_) | 837 for (const auto& mdpinfo : dump_providers_for_polling_) |
812 mdpinfo->dump_provider->SuspendFastMemoryPolling(); | 838 mdpinfo->dump_provider->SuspendFastMemoryPolling(); |
813 dump_providers_for_polling_.clear(); | 839 dump_providers_for_polling_.clear(); |
840 trigger = dump_trigger_.get(); | |
814 } | 841 } |
842 trigger->Disable(); | |
815 } | 843 } |
816 | 844 |
817 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { | 845 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) { |
818 AutoLock lock(lock_); | 846 AutoLock lock(lock_); |
819 if (!session_state_) | 847 if (!session_state_) |
820 return false; | 848 return false; |
821 return session_state_->memory_dump_config().allowed_dump_modes.count( | 849 return session_state_->memory_dump_config().allowed_dump_modes.count( |
822 dump_mode) != 0; | 850 dump_mode) != 0; |
823 } | 851 } |
824 | 852 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
878 const MemoryDumpArgs& dump_args) { | 906 const MemoryDumpArgs& dump_args) { |
879 auto iter = process_dumps.find(pid); | 907 auto iter = process_dumps.find(pid); |
880 if (iter == process_dumps.end()) { | 908 if (iter == process_dumps.end()) { |
881 std::unique_ptr<ProcessMemoryDump> new_pmd( | 909 std::unique_ptr<ProcessMemoryDump> new_pmd( |
882 new ProcessMemoryDump(session_state, dump_args)); | 910 new ProcessMemoryDump(session_state, dump_args)); |
883 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 911 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
884 } | 912 } |
885 return iter->second.get(); | 913 return iter->second.get(); |
886 } | 914 } |
887 | 915 |
888 MemoryDumpManager::PeriodicGlobalDumpTimer::PeriodicGlobalDumpTimer() {} | |
889 | |
890 MemoryDumpManager::PeriodicGlobalDumpTimer::~PeriodicGlobalDumpTimer() { | |
891 Stop(); | |
892 } | |
893 | |
894 void MemoryDumpManager::PeriodicGlobalDumpTimer::Start( | |
895 const std::vector<TraceConfig::MemoryDumpConfig::Trigger>& triggers_list) { | |
896 if (triggers_list.empty()) | |
897 return; | |
898 | |
899 // At the moment the periodic support is limited to at most one periodic | |
900 // trigger per dump mode. All intervals should be an integer multiple of the | |
901 // smallest interval specified. | |
902 periodic_dumps_count_ = 0; | |
903 uint32_t min_timer_period_ms = std::numeric_limits<uint32_t>::max(); | |
904 uint32_t light_dump_period_ms = 0; | |
905 uint32_t heavy_dump_period_ms = 0; | |
906 DCHECK_LE(triggers_list.size(), 3u); | |
907 auto* mdm = MemoryDumpManager::GetInstance(); | |
908 for (const TraceConfig::MemoryDumpConfig::Trigger& config : triggers_list) { | |
909 DCHECK_NE(0u, config.min_time_between_dumps_ms); | |
910 DCHECK_EQ(MemoryDumpType::PERIODIC_INTERVAL, config.trigger_type) | |
911 << "Only periodic_interval triggers are suppported"; | |
912 switch (config.level_of_detail) { | |
913 case MemoryDumpLevelOfDetail::BACKGROUND: | |
914 DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::BACKGROUND)); | |
915 break; | |
916 case MemoryDumpLevelOfDetail::LIGHT: | |
917 DCHECK_EQ(0u, light_dump_period_ms); | |
918 DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::LIGHT)); | |
919 light_dump_period_ms = config.min_time_between_dumps_ms; | |
920 break; | |
921 case MemoryDumpLevelOfDetail::DETAILED: | |
922 DCHECK_EQ(0u, heavy_dump_period_ms); | |
923 DCHECK(mdm->IsDumpModeAllowed(MemoryDumpLevelOfDetail::DETAILED)); | |
924 heavy_dump_period_ms = config.min_time_between_dumps_ms; | |
925 break; | |
926 } | |
927 min_timer_period_ms = | |
928 std::min(min_timer_period_ms, config.min_time_between_dumps_ms); | |
929 } | |
930 | |
931 DCHECK_EQ(0u, light_dump_period_ms % min_timer_period_ms); | |
932 light_dump_rate_ = light_dump_period_ms / min_timer_period_ms; | |
933 DCHECK_EQ(0u, heavy_dump_period_ms % min_timer_period_ms); | |
934 heavy_dump_rate_ = heavy_dump_period_ms / min_timer_period_ms; | |
935 | |
936 timer_.Start(FROM_HERE, TimeDelta::FromMilliseconds(min_timer_period_ms), | |
937 base::Bind(&PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump, | |
938 base::Unretained(this))); | |
939 } | |
940 | |
941 void MemoryDumpManager::PeriodicGlobalDumpTimer::Stop() { | |
942 if (IsRunning()) { | |
943 timer_.Stop(); | |
944 } | |
945 } | |
946 | |
947 bool MemoryDumpManager::PeriodicGlobalDumpTimer::IsRunning() { | |
948 return timer_.IsRunning(); | |
949 } | |
950 | |
951 void MemoryDumpManager::PeriodicGlobalDumpTimer::RequestPeriodicGlobalDump() { | |
952 MemoryDumpLevelOfDetail level_of_detail = MemoryDumpLevelOfDetail::BACKGROUND; | |
953 if (light_dump_rate_ > 0 && periodic_dumps_count_ % light_dump_rate_ == 0) | |
954 level_of_detail = MemoryDumpLevelOfDetail::LIGHT; | |
955 if (heavy_dump_rate_ > 0 && periodic_dumps_count_ % heavy_dump_rate_ == 0) | |
956 level_of_detail = MemoryDumpLevelOfDetail::DETAILED; | |
957 ++periodic_dumps_count_; | |
958 | |
959 MemoryDumpManager::GetInstance()->RequestGlobalDump( | |
960 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | |
961 } | |
962 | |
963 } // namespace trace_event | 916 } // namespace trace_event |
964 } // namespace base | 917 } // namespace base |
OLD | NEW |