Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(83)

Side by Side Diff: base/trace_event/memory_dump_manager.cc

Issue 2861133002: memory-infra: Move dump level check to observer and rename session state (Closed)
Patch Set: rebase Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 <inttypes.h> 7 #include <inttypes.h>
8 #include <stdio.h> 8 #include <stdio.h>
9 9
10 #include <algorithm> 10 #include <algorithm>
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 const ProcessMemoryDump* pmd, 76 const ProcessMemoryDump* pmd,
77 MemoryDumpCallbackResult::OSMemDump* osDump) { 77 MemoryDumpCallbackResult::OSMemDump* osDump) {
78 if (pmd->has_process_totals()) { 78 if (pmd->has_process_totals()) {
79 const ProcessMemoryTotals* totals = pmd->process_totals(); 79 const ProcessMemoryTotals* totals = pmd->process_totals();
80 osDump->resident_set_kb = totals->resident_set_bytes() / 1024; 80 osDump->resident_set_kb = totals->resident_set_bytes() / 1024;
81 osDump->platform_private_footprint = totals->GetPlatformPrivateFootprint(); 81 osDump->platform_private_footprint = totals->GetPlatformPrivateFootprint();
82 } 82 }
83 } 83 }
84 84
85 // Proxy class which wraps a ConvertableToTraceFormat owned by the 85 // Proxy class which wraps a ConvertableToTraceFormat owned by the
86 // |session_state| into a proxy object that can be added to the trace event log. 86 // |heap_profiler_serialization_state| into a proxy object that can be added to
87 // This is to solve the problem that the MemoryDumpSessionState is refcounted 87 // the trace event log. This is to solve the problem that the
88 // but the tracing subsystem wants a std::unique_ptr<ConvertableToTraceFormat>. 88 // MemoryDumpSessionState is refcounted but the tracing subsystem wants a
89 // std::unique_ptr<ConvertableToTraceFormat>.
89 template <typename T> 90 template <typename T>
90 struct SessionStateConvertableProxy : public ConvertableToTraceFormat { 91 struct SessionStateConvertableProxy : public ConvertableToTraceFormat {
91 using GetterFunctPtr = T* (MemoryDumpSessionState::*)() const; 92 using GetterFunctPtr = T* (MemoryDumpSessionState::*)() const;
92 93
93 SessionStateConvertableProxy( 94 SessionStateConvertableProxy(
94 scoped_refptr<MemoryDumpSessionState> session_state, 95 scoped_refptr<MemoryDumpSessionState> heap_profiler_serialization_state,
95 GetterFunctPtr getter_function) 96 GetterFunctPtr getter_function)
96 : session_state(session_state), getter_function(getter_function) {} 97 : heap_profiler_serialization_state(heap_profiler_serialization_state),
98 getter_function(getter_function) {}
97 99
98 void AppendAsTraceFormat(std::string* out) const override { 100 void AppendAsTraceFormat(std::string* out) const override {
99 return (session_state.get()->*getter_function)()->AppendAsTraceFormat(out); 101 return (heap_profiler_serialization_state.get()->*getter_function)()
102 ->AppendAsTraceFormat(out);
100 } 103 }
101 104
102 void EstimateTraceMemoryOverhead( 105 void EstimateTraceMemoryOverhead(
103 TraceEventMemoryOverhead* overhead) override { 106 TraceEventMemoryOverhead* overhead) override {
104 return (session_state.get()->*getter_function)() 107 return (heap_profiler_serialization_state.get()->*getter_function)()
105 ->EstimateTraceMemoryOverhead(overhead); 108 ->EstimateTraceMemoryOverhead(overhead);
106 } 109 }
107 110
108 scoped_refptr<MemoryDumpSessionState> session_state; 111 scoped_refptr<MemoryDumpSessionState> heap_profiler_serialization_state;
109 GetterFunctPtr const getter_function; 112 GetterFunctPtr const getter_function;
110 }; 113 };
111 114
112 void OnPeakDetected(MemoryDumpLevelOfDetail level_of_detail) { 115 void OnPeakDetected(MemoryDumpLevelOfDetail level_of_detail) {
113 MemoryDumpManager::GetInstance()->RequestGlobalDump( 116 MemoryDumpManager::GetInstance()->RequestGlobalDump(
114 MemoryDumpType::PEAK_MEMORY_USAGE, level_of_detail); 117 MemoryDumpType::PEAK_MEMORY_USAGE, level_of_detail);
115 } 118 }
116 119
117 void OnPeriodicSchedulerTick(MemoryDumpLevelOfDetail level_of_detail) { 120 void OnPeriodicSchedulerTick(MemoryDumpLevelOfDetail level_of_detail) {
118 MemoryDumpManager::GetInstance()->RequestGlobalDump( 121 MemoryDumpManager::GetInstance()->RequestGlobalDump(
(...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after
400 (*mdp_iter)->disabled = true; 403 (*mdp_iter)->disabled = true;
401 dump_providers_.erase(mdp_iter); 404 dump_providers_.erase(mdp_iter);
402 } 405 }
403 406
404 void MemoryDumpManager::RequestGlobalDump( 407 void MemoryDumpManager::RequestGlobalDump(
405 MemoryDumpType dump_type, 408 MemoryDumpType dump_type,
406 MemoryDumpLevelOfDetail level_of_detail, 409 MemoryDumpLevelOfDetail level_of_detail,
407 const GlobalMemoryDumpCallback& callback) { 410 const GlobalMemoryDumpCallback& callback) {
408 // Bail out immediately if tracing is not enabled at all or if the dump mode 411 // Bail out immediately if tracing is not enabled at all or if the dump mode
409 // is not allowed. 412 // is not allowed.
410 if (!UNLIKELY(subtle::NoBarrier_Load(&is_enabled_)) || 413 if (!UNLIKELY(subtle::NoBarrier_Load(&is_enabled_))) {
411 !IsDumpModeAllowed(level_of_detail)) {
412 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory 414 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory
413 << " tracing category is not enabled or the requested dump mode is " 415 << " tracing category is not enabled.";
414 "not allowed by trace config.";
415 if (!callback.is_null()) 416 if (!callback.is_null())
416 callback.Run(0u /* guid */, false /* success */); 417 callback.Run(0u /* guid */, false /* success */);
417 return; 418 return;
418 } 419 }
419 420
420 const uint64_t guid = 421 const uint64_t guid =
421 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); 422 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext());
422 423
423 // Creates an async event to keep track of the global dump evolution. 424 // Creates an async event to keep track of the global dump evolution.
424 // The |wrapped_callback| will generate the ASYNC_END event and then invoke 425 // The |wrapped_callback| will generate the ASYNC_END event and then invoke
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
493 ->GetCurrentTraceConfig() 494 ->GetCurrentTraceConfig()
494 .IsArgumentFilterEnabled()) { 495 .IsArgumentFilterEnabled()) {
495 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail); 496 CHECK_EQ(MemoryDumpLevelOfDetail::BACKGROUND, args.level_of_detail);
496 } 497 }
497 498
498 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state; 499 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state;
499 { 500 {
500 AutoLock lock(lock_); 501 AutoLock lock(lock_);
501 502
502 pmd_async_state.reset(new ProcessMemoryDumpAsyncState( 503 pmd_async_state.reset(new ProcessMemoryDumpAsyncState(
503 args, dump_providers_, session_state_, callback, 504 args, dump_providers_, heap_profiler_serialization_state_, callback,
504 GetOrCreateBgTaskRunnerLocked())); 505 GetOrCreateBgTaskRunnerLocked()));
505 506
506 // Safety check to prevent reaching here without calling RequestGlobalDump,
507 // with disallowed modes. If |session_state_| is null then tracing is
508 // disabled.
509 CHECK(!session_state_ ||
510 session_state_->IsDumpModeAllowed(args.level_of_detail));
511
512 // If enabled, holds back the peak detector resetting its estimation window. 507 // If enabled, holds back the peak detector resetting its estimation window.
513 MemoryPeakDetector::GetInstance()->Throttle(); 508 MemoryPeakDetector::GetInstance()->Throttle();
514 } 509 }
515 510
516 // Start the process dump. This involves task runner hops as specified by the 511 // Start the process dump. This involves task runner hops as specified by the
517 // MemoryDumpProvider(s) in RegisterDumpProvider()). 512 // MemoryDumpProvider(s) in RegisterDumpProvider()).
518 SetupNextMemoryDump(std::move(pmd_async_state)); 513 SetupNextMemoryDump(std::move(pmd_async_state));
519 } 514 }
520 515
521 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A 516 // PostTask InvokeOnMemoryDump() to the dump provider's sequenced task runner. A
(...skipping 246 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 pmd_async_state->callback.Run(dump_guid, dump_successful, result); 763 pmd_async_state->callback.Run(dump_guid, dump_successful, result);
769 pmd_async_state->callback.Reset(); 764 pmd_async_state->callback.Reset();
770 } 765 }
771 766
772 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", 767 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump",
773 TRACE_ID_LOCAL(dump_guid)); 768 TRACE_ID_LOCAL(dump_guid));
774 } 769 }
775 770
776 void MemoryDumpManager::Enable( 771 void MemoryDumpManager::Enable(
777 const TraceConfig::MemoryDumpConfig& memory_dump_config) { 772 const TraceConfig::MemoryDumpConfig& memory_dump_config) {
778 773 scoped_refptr<MemoryDumpSessionState> heap_profiler_serialization_state =
Primiano Tucci (use gerrit) 2017/05/05 13:38:24 sg but can we move this to its own function in the
779 scoped_refptr<MemoryDumpSessionState> session_state =
780 new MemoryDumpSessionState; 774 new MemoryDumpSessionState;
781 session_state->SetAllowedDumpModes(memory_dump_config.allowed_dump_modes); 775 heap_profiler_serialization_state
782 session_state->set_heap_profiler_breakdown_threshold_bytes( 776 ->set_heap_profiler_breakdown_threshold_bytes(
783 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); 777 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes);
784 if (heap_profiling_enabled_) { 778 if (heap_profiling_enabled_) {
785 // If heap profiling is enabled, the stack frame deduplicator and type name 779 // If heap profiling is enabled, the stack frame deduplicator and type name
786 // deduplicator will be in use. Add a metadata events to write the frames 780 // deduplicator will be in use. Add a metadata events to write the frames
787 // and type IDs. 781 // and type IDs.
788 session_state->SetStackFrameDeduplicator( 782 heap_profiler_serialization_state->SetStackFrameDeduplicator(
789 WrapUnique(new StackFrameDeduplicator)); 783 WrapUnique(new StackFrameDeduplicator));
790 784
791 session_state->SetTypeNameDeduplicator( 785 heap_profiler_serialization_state->SetTypeNameDeduplicator(
792 WrapUnique(new TypeNameDeduplicator)); 786 WrapUnique(new TypeNameDeduplicator));
793 787
794 TRACE_EVENT_API_ADD_METADATA_EVENT( 788 TRACE_EVENT_API_ADD_METADATA_EVENT(
795 TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames", 789 TraceLog::GetCategoryGroupEnabled("__metadata"), "stackFrames",
796 "stackFrames", 790 "stackFrames",
797 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>( 791 MakeUnique<SessionStateConvertableProxy<StackFrameDeduplicator>>(
798 session_state, &MemoryDumpSessionState::stack_frame_deduplicator)); 792 heap_profiler_serialization_state,
793 &MemoryDumpSessionState::stack_frame_deduplicator));
799 794
800 TRACE_EVENT_API_ADD_METADATA_EVENT( 795 TRACE_EVENT_API_ADD_METADATA_EVENT(
801 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", 796 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames",
802 "typeNames", 797 "typeNames",
803 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( 798 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>(
804 session_state, &MemoryDumpSessionState::type_name_deduplicator)); 799 heap_profiler_serialization_state,
800 &MemoryDumpSessionState::type_name_deduplicator));
805 } 801 }
806 802
807 AutoLock lock(lock_); 803 AutoLock lock(lock_);
808 804
809 // At this point we must have the ability to request global dumps. 805 // At this point we must have the ability to request global dumps.
810 DCHECK(!request_dump_function_.is_null()); 806 DCHECK(!request_dump_function_.is_null());
811 session_state_ = session_state; 807 heap_profiler_serialization_state_ = heap_profiler_serialization_state;
812 808
813 subtle::NoBarrier_Store(&is_enabled_, 1); 809 subtle::NoBarrier_Store(&is_enabled_, 1);
814 810
815 MemoryDumpScheduler::Config periodic_config; 811 MemoryDumpScheduler::Config periodic_config;
816 bool peak_detector_configured = false; 812 bool peak_detector_configured = false;
817 for (const auto& trigger : memory_dump_config.triggers) { 813 for (const auto& trigger : memory_dump_config.triggers) {
818 if (!session_state_->IsDumpModeAllowed(trigger.level_of_detail)) {
819 NOTREACHED();
820 continue;
821 }
822 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) { 814 if (trigger.trigger_type == MemoryDumpType::PERIODIC_INTERVAL) {
823 if (periodic_config.triggers.empty()) { 815 if (periodic_config.triggers.empty()) {
824 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick); 816 periodic_config.callback = BindRepeating(&OnPeriodicSchedulerTick);
825 } 817 }
826 periodic_config.triggers.push_back( 818 periodic_config.triggers.push_back(
827 {trigger.level_of_detail, trigger.min_time_between_dumps_ms}); 819 {trigger.level_of_detail, trigger.min_time_between_dumps_ms});
828 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) { 820 } else if (trigger.trigger_type == MemoryDumpType::PEAK_MEMORY_USAGE) {
829 // At most one peak trigger is allowed. 821 // At most one peak trigger is allowed.
830 CHECK(!peak_detector_configured); 822 CHECK(!peak_detector_configured);
831 peak_detector_configured = true; 823 peak_detector_configured = true;
(...skipping 30 matching lines...) Expand all
862 // There might be a memory dump in progress while this happens. Therefore, 854 // There might be a memory dump in progress while this happens. Therefore,
863 // ensure that the MDM state which depends on the tracing enabled / disabled 855 // ensure that the MDM state which depends on the tracing enabled / disabled
864 // state is always accessed by the dumping methods holding the |lock_|. 856 // state is always accessed by the dumping methods holding the |lock_|.
865 if (!subtle::NoBarrier_Load(&is_enabled_)) 857 if (!subtle::NoBarrier_Load(&is_enabled_))
866 return; 858 return;
867 subtle::NoBarrier_Store(&is_enabled_, 0); 859 subtle::NoBarrier_Store(&is_enabled_, 0);
868 { 860 {
869 AutoLock lock(lock_); 861 AutoLock lock(lock_);
870 MemoryDumpScheduler::GetInstance()->Stop(); 862 MemoryDumpScheduler::GetInstance()->Stop();
871 MemoryPeakDetector::GetInstance()->TearDown(); 863 MemoryPeakDetector::GetInstance()->TearDown();
872 session_state_ = nullptr; 864 heap_profiler_serialization_state_ = nullptr;
873 } 865 }
874 } 866 }
875 867
876 bool MemoryDumpManager::IsDumpModeAllowed(MemoryDumpLevelOfDetail dump_mode) {
877 AutoLock lock(lock_);
878 if (!session_state_)
879 return false;
880 return session_state_->IsDumpModeAllowed(dump_mode);
881 }
882
883 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( 868 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState(
884 MemoryDumpRequestArgs req_args, 869 MemoryDumpRequestArgs req_args,
885 const MemoryDumpProviderInfo::OrderedSet& dump_providers, 870 const MemoryDumpProviderInfo::OrderedSet& dump_providers,
886 scoped_refptr<MemoryDumpSessionState> session_state, 871 scoped_refptr<MemoryDumpSessionState> heap_profiler_serialization_state,
887 ProcessMemoryDumpCallback callback, 872 ProcessMemoryDumpCallback callback,
888 scoped_refptr<SequencedTaskRunner> dump_thread_task_runner) 873 scoped_refptr<SequencedTaskRunner> dump_thread_task_runner)
889 : req_args(req_args), 874 : req_args(req_args),
890 session_state(std::move(session_state)), 875 heap_profiler_serialization_state(
876 std::move(heap_profiler_serialization_state)),
891 callback(callback), 877 callback(callback),
892 dump_successful(true), 878 dump_successful(true),
893 callback_task_runner(ThreadTaskRunnerHandle::Get()), 879 callback_task_runner(ThreadTaskRunnerHandle::Get()),
894 dump_thread_task_runner(std::move(dump_thread_task_runner)) { 880 dump_thread_task_runner(std::move(dump_thread_task_runner)) {
895 pending_dump_providers.reserve(dump_providers.size()); 881 pending_dump_providers.reserve(dump_providers.size());
896 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); 882 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend());
897 } 883 }
898 884
899 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { 885 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() {
900 } 886 }
901 887
902 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: 888 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState::
903 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid, 889 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid,
904 const MemoryDumpArgs& dump_args) { 890 const MemoryDumpArgs& dump_args) {
905 auto iter = process_dumps.find(pid); 891 auto iter = process_dumps.find(pid);
906 if (iter == process_dumps.end()) { 892 if (iter == process_dumps.end()) {
907 std::unique_ptr<ProcessMemoryDump> new_pmd( 893 std::unique_ptr<ProcessMemoryDump> new_pmd(
908 new ProcessMemoryDump(session_state, dump_args)); 894 new ProcessMemoryDump(heap_profiler_serialization_state, dump_args));
909 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; 895 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first;
910 } 896 }
911 return iter->second.get(); 897 return iter->second.get();
912 } 898 }
913 899
914 } // namespace trace_event 900 } // namespace trace_event
915 } // namespace base 901 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698