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 <inttypes.h> | 7 #include <inttypes.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
174 return Singleton<MemoryDumpManager, | 174 return Singleton<MemoryDumpManager, |
175 LeakySingletonTraits<MemoryDumpManager>>::get(); | 175 LeakySingletonTraits<MemoryDumpManager>>::get(); |
176 } | 176 } |
177 | 177 |
178 // static | 178 // static |
179 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { | 179 void MemoryDumpManager::SetInstanceForTesting(MemoryDumpManager* instance) { |
180 g_instance_for_testing = instance; | 180 g_instance_for_testing = instance; |
181 } | 181 } |
182 | 182 |
183 MemoryDumpManager::MemoryDumpManager() | 183 MemoryDumpManager::MemoryDumpManager() |
184 : memory_tracing_enabled_(0), | 184 : is_coordinator_(false), |
| 185 memory_tracing_enabled_(0), |
185 tracing_process_id_(kInvalidTracingProcessId), | 186 tracing_process_id_(kInvalidTracingProcessId), |
186 dumper_registrations_ignored_for_testing_(false), | 187 dumper_registrations_ignored_for_testing_(false), |
187 heap_profiling_enabled_(false) { | 188 heap_profiling_enabled_(false) { |
188 g_next_guid.GetNext(); // Make sure that first guid is not zero. | 189 g_next_guid.GetNext(); // Make sure that first guid is not zero. |
189 | 190 |
190 // At this point the command line may not be initialized but we try to | 191 // At this point the command line may not be initialized but we try to |
191 // enable the heap profiler to capture allocations as soon as possible. | 192 // enable the heap profiler to capture allocations as soon as possible. |
192 EnableHeapProfilingIfNeeded(); | 193 EnableHeapProfilingIfNeeded(); |
193 | 194 |
194 strict_thread_check_blacklist_.insert(std::begin(kStrictThreadCheckBlacklist), | 195 strict_thread_check_blacklist_.insert(std::begin(kStrictThreadCheckBlacklist), |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
230 CHECK(false) << "Invalid mode '" << profiling_mode << "' for " | 231 CHECK(false) << "Invalid mode '" << profiling_mode << "' for " |
231 << switches::kEnableHeapProfiling << " flag."; | 232 << switches::kEnableHeapProfiling << " flag."; |
232 } | 233 } |
233 | 234 |
234 for (auto mdp : dump_providers_) | 235 for (auto mdp : dump_providers_) |
235 mdp->dump_provider->OnHeapProfilingEnabled(true); | 236 mdp->dump_provider->OnHeapProfilingEnabled(true); |
236 heap_profiling_enabled_ = true; | 237 heap_profiling_enabled_ = true; |
237 } | 238 } |
238 | 239 |
239 void MemoryDumpManager::Initialize( | 240 void MemoryDumpManager::Initialize( |
240 std::unique_ptr<MemoryDumpManagerDelegate> delegate) { | 241 RequestGlobalDumpFunction request_dump_function, |
| 242 bool is_coordinator) { |
241 { | 243 { |
242 AutoLock lock(lock_); | 244 AutoLock lock(lock_); |
243 DCHECK(delegate); | 245 DCHECK(!request_dump_function.is_null()); |
244 DCHECK(!delegate_); | 246 DCHECK(request_dump_function_.is_null()); |
245 delegate_ = std::move(delegate); | 247 request_dump_function_ = request_dump_function; |
| 248 is_coordinator_ = is_coordinator; |
246 EnableHeapProfilingIfNeeded(); | 249 EnableHeapProfilingIfNeeded(); |
247 } | 250 } |
248 | 251 |
249 // Enable the core dump providers. | 252 // Enable the core dump providers. |
250 #if defined(MALLOC_MEMORY_TRACING_SUPPORTED) | 253 #if defined(MALLOC_MEMORY_TRACING_SUPPORTED) |
251 RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr); | 254 RegisterDumpProvider(MallocDumpProvider::GetInstance(), "Malloc", nullptr); |
252 #endif | 255 #endif |
253 | 256 |
254 #if defined(OS_ANDROID) | 257 #if defined(OS_ANDROID) |
255 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap", | 258 RegisterDumpProvider(JavaHeapDumpProvider::GetInstance(), "JavaHeap", |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
449 | 452 |
450 // Creates an async event to keep track of the global dump evolution. | 453 // Creates an async event to keep track of the global dump evolution. |
451 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 454 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
452 // the real |callback| provided by the caller. | 455 // the real |callback| provided by the caller. |
453 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( | 456 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
454 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", | 457 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", |
455 MemoryDumpTypeToString(dump_type), "level_of_detail", | 458 MemoryDumpTypeToString(dump_type), "level_of_detail", |
456 MemoryDumpLevelOfDetailToString(level_of_detail)); | 459 MemoryDumpLevelOfDetailToString(level_of_detail)); |
457 GlobalMemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); | 460 GlobalMemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); |
458 | 461 |
459 // The delegate will coordinate the IPC broadcast and at some point invoke | 462 // The embedder will coordinate the IPC broadcast and at some point invoke |
460 // CreateProcessDump() to get a dump for the current process. | 463 // CreateProcessDump() to get a dump for the current process. |
461 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; | 464 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; |
462 delegate_->RequestGlobalMemoryDump(args, wrapped_callback); | 465 request_dump_function_.Run(args, wrapped_callback); |
463 } | 466 } |
464 | 467 |
465 void MemoryDumpManager::GetDumpProvidersForPolling( | 468 void MemoryDumpManager::GetDumpProvidersForPolling( |
466 std::vector<scoped_refptr<MemoryDumpProviderInfo>>* providers) { | 469 std::vector<scoped_refptr<MemoryDumpProviderInfo>>* providers) { |
467 DCHECK(providers->empty()); | 470 DCHECK(providers->empty()); |
468 AutoLock lock(lock_); | 471 AutoLock lock(lock_); |
469 for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) { | 472 for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) { |
470 if (mdp->options.is_fast_polling_supported) | 473 if (mdp->options.is_fast_polling_supported) |
471 providers->push_back(mdp); | 474 providers->push_back(mdp); |
472 } | 475 } |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 | 819 |
817 TRACE_EVENT_API_ADD_METADATA_EVENT( | 820 TRACE_EVENT_API_ADD_METADATA_EVENT( |
818 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", | 821 TraceLog::GetCategoryGroupEnabled("__metadata"), "typeNames", |
819 "typeNames", | 822 "typeNames", |
820 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( | 823 MakeUnique<SessionStateConvertableProxy<TypeNameDeduplicator>>( |
821 session_state, &MemoryDumpSessionState::type_name_deduplicator)); | 824 session_state, &MemoryDumpSessionState::type_name_deduplicator)); |
822 } | 825 } |
823 | 826 |
824 AutoLock lock(lock_); | 827 AutoLock lock(lock_); |
825 | 828 |
826 DCHECK(delegate_); // At this point we must have a delegate. | 829 // At this point we must have the ability to request global dumps. |
| 830 DCHECK(!request_dump_function_.is_null()); |
827 session_state_ = session_state; | 831 session_state_ = session_state; |
828 | 832 |
829 DCHECK(!dump_thread_); | 833 DCHECK(!dump_thread_); |
830 dump_thread_ = std::move(dump_thread); | 834 dump_thread_ = std::move(dump_thread); |
831 | 835 |
832 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); | 836 subtle::NoBarrier_Store(&memory_tracing_enabled_, 1); |
833 | 837 |
834 MemoryDumpScheduler::Config periodic_config; | 838 MemoryDumpScheduler::Config periodic_config; |
835 bool peak_detector_configured = false; | 839 bool peak_detector_configured = false; |
836 for (const auto& trigger : memory_dump_config.triggers) { | 840 for (const auto& trigger : memory_dump_config.triggers) { |
(...skipping 19 matching lines...) Expand all Loading... |
856 | 860 |
857 MemoryPeakDetector::Config peak_config; | 861 MemoryPeakDetector::Config peak_config; |
858 peak_config.polling_interval_ms = 10; | 862 peak_config.polling_interval_ms = 10; |
859 peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms; | 863 peak_config.min_time_between_peaks_ms = trigger.min_time_between_dumps_ms; |
860 peak_config.enable_verbose_poll_tracing = | 864 peak_config.enable_verbose_poll_tracing = |
861 trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED; | 865 trigger.level_of_detail == MemoryDumpLevelOfDetail::DETAILED; |
862 MemoryPeakDetector::GetInstance()->Start(peak_config); | 866 MemoryPeakDetector::GetInstance()->Start(peak_config); |
863 | 867 |
864 // When peak detection is enabled, trigger a dump straight away as it | 868 // When peak detection is enabled, trigger a dump straight away as it |
865 // gives a good reference point for analyzing the trace. | 869 // gives a good reference point for analyzing the trace. |
866 if (delegate_->IsCoordinator()) { | 870 if (is_coordinator_) { |
867 dump_thread_->task_runner()->PostTask( | 871 dump_thread_->task_runner()->PostTask( |
868 FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail)); | 872 FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail)); |
869 } | 873 } |
870 } | 874 } |
871 } | 875 } |
872 | 876 |
873 // Only coordinator process triggers periodic global memory dumps. | 877 // Only coordinator process triggers periodic global memory dumps. |
874 if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) { | 878 if (is_coordinator_ && !periodic_config.triggers.empty()) { |
875 MemoryDumpScheduler::GetInstance()->Start(periodic_config, | 879 MemoryDumpScheduler::GetInstance()->Start(periodic_config, |
876 dump_thread_->task_runner()); | 880 dump_thread_->task_runner()); |
877 } | 881 } |
878 } | 882 } |
879 | 883 |
880 void MemoryDumpManager::Disable() { | 884 void MemoryDumpManager::Disable() { |
881 // There might be a memory dump in progress while this happens. Therefore, | 885 // There might be a memory dump in progress while this happens. Therefore, |
882 // ensure that the MDM state which depends on the tracing enabled / disabled | 886 // ensure that the MDM state which depends on the tracing enabled / disabled |
883 // state is always accessed by the dumping methods holding the |lock_|. | 887 // state is always accessed by the dumping methods holding the |lock_|. |
884 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) | 888 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
932 if (iter == process_dumps.end()) { | 936 if (iter == process_dumps.end()) { |
933 std::unique_ptr<ProcessMemoryDump> new_pmd( | 937 std::unique_ptr<ProcessMemoryDump> new_pmd( |
934 new ProcessMemoryDump(session_state, dump_args)); | 938 new ProcessMemoryDump(session_state, dump_args)); |
935 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 939 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
936 } | 940 } |
937 return iter->second.get(); | 941 return iter->second.get(); |
938 } | 942 } |
939 | 943 |
940 } // namespace trace_event | 944 } // namespace trace_event |
941 } // namespace base | 945 } // namespace base |
OLD | NEW |