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 113 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
124 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); | 124 MemoryDumpType::PERIODIC_INTERVAL, level_of_detail); |
125 } | 125 } |
126 | 126 |
127 } // namespace | 127 } // namespace |
128 | 128 |
129 // static | 129 // static |
130 const char* const MemoryDumpManager::kTraceCategory = | 130 const char* const MemoryDumpManager::kTraceCategory = |
131 TRACE_DISABLED_BY_DEFAULT("memory-infra"); | 131 TRACE_DISABLED_BY_DEFAULT("memory-infra"); |
132 | 132 |
133 // static | 133 // static |
134 const char* const MemoryDumpManager::kLogPrefix = "Memory-infra dump"; | |
135 | |
136 // static | |
137 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; | 134 const int MemoryDumpManager::kMaxConsecutiveFailuresCount = 3; |
138 | 135 |
139 // static | 136 // static |
140 const uint64_t MemoryDumpManager::kInvalidTracingProcessId = 0; | 137 const uint64_t MemoryDumpManager::kInvalidTracingProcessId = 0; |
141 | 138 |
142 // static | 139 // static |
143 const char* const MemoryDumpManager::kSystemAllocatorPoolName = | 140 const char* const MemoryDumpManager::kSystemAllocatorPoolName = |
144 #if defined(MALLOC_MEMORY_TRACING_SUPPORTED) | 141 #if defined(MALLOC_MEMORY_TRACING_SUPPORTED) |
145 MallocDumpProvider::kAllocatedObjects; | 142 MallocDumpProvider::kAllocatedObjects; |
146 #else | 143 #else |
147 nullptr; | 144 nullptr; |
148 #endif | 145 #endif |
149 | 146 |
150 // static | 147 // static |
151 MemoryDumpManager* MemoryDumpManager::GetInstance() { | 148 MemoryDumpManager* MemoryDumpManager::GetInstance() { |
152 if (g_instance_for_testing) | 149 if (g_instance_for_testing) |
153 return g_instance_for_testing; | 150 return g_instance_for_testing; |
154 | 151 |
155 return Singleton<MemoryDumpManager, | 152 return Singleton<MemoryDumpManager, |
156 LeakySingletonTraits<MemoryDumpManager>>::get(); | 153 LeakySingletonTraits<MemoryDumpManager>>::get(); |
157 } | 154 } |
158 | 155 |
159 // static | 156 // static |
160 std::unique_ptr<MemoryDumpManager> | 157 std::unique_ptr<MemoryDumpManager> |
161 MemoryDumpManager::CreateInstanceForTesting() { | 158 MemoryDumpManager::CreateInstanceForTesting() { |
| 159 DCHECK(!g_instance_for_testing); |
162 std::unique_ptr<MemoryDumpManager> instance(new MemoryDumpManager()); | 160 std::unique_ptr<MemoryDumpManager> instance(new MemoryDumpManager()); |
163 g_instance_for_testing = instance.get(); | 161 g_instance_for_testing = instance.get(); |
164 return instance; | 162 return instance; |
165 } | 163 } |
166 | 164 |
167 MemoryDumpManager::MemoryDumpManager() | 165 MemoryDumpManager::MemoryDumpManager() |
168 : is_coordinator_(false), | 166 : is_coordinator_(false), |
169 tracing_process_id_(kInvalidTracingProcessId), | 167 tracing_process_id_(kInvalidTracingProcessId), |
170 dumper_registrations_ignored_for_testing_(false), | 168 dumper_registrations_ignored_for_testing_(false), |
171 heap_profiling_enabled_(false) { | 169 heap_profiling_enabled_(false) { |
(...skipping 249 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
421 // to just skip it, without actually invoking the |mdp|, which might be | 419 // to just skip it, without actually invoking the |mdp|, which might be |
422 // destroyed by the caller soon after this method returns. | 420 // destroyed by the caller soon after this method returns. |
423 (*mdp_iter)->disabled = true; | 421 (*mdp_iter)->disabled = true; |
424 dump_providers_.erase(mdp_iter); | 422 dump_providers_.erase(mdp_iter); |
425 } | 423 } |
426 | 424 |
427 void MemoryDumpManager::RequestGlobalDump( | 425 void MemoryDumpManager::RequestGlobalDump( |
428 MemoryDumpType dump_type, | 426 MemoryDumpType dump_type, |
429 MemoryDumpLevelOfDetail level_of_detail, | 427 MemoryDumpLevelOfDetail level_of_detail, |
430 const GlobalMemoryDumpCallback& callback) { | 428 const GlobalMemoryDumpCallback& callback) { |
431 // If |request_dump_function_| is null MDM hasn't been initialized yet. | 429 if (!is_initialized()) { |
432 if (request_dump_function_.is_null()) { | 430 VLOG(1) << "RequestGlobalDump() FAIL: MemoryDumpManager is not initialized"; |
433 VLOG(1) << kLogPrefix << " failed because" | |
434 << " memory dump manager is not enabled."; | |
435 if (!callback.is_null()) | 431 if (!callback.is_null()) |
436 callback.Run(0u /* guid */, false /* success */); | 432 callback.Run(0u /* guid */, false /* success */); |
437 return; | 433 return; |
438 } | 434 } |
439 | 435 |
440 const uint64_t guid = | 436 const uint64_t guid = |
441 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 437 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
442 | 438 |
443 // Creates an async event to keep track of the global dump evolution. | 439 // Creates an async event to keep track of the global dump evolution. |
444 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 440 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
(...skipping 16 matching lines...) Expand all Loading... |
461 AutoLock lock(lock_); | 457 AutoLock lock(lock_); |
462 for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) { | 458 for (const scoped_refptr<MemoryDumpProviderInfo>& mdp : dump_providers_) { |
463 if (mdp->options.is_fast_polling_supported) | 459 if (mdp->options.is_fast_polling_supported) |
464 providers->push_back(mdp); | 460 providers->push_back(mdp); |
465 } | 461 } |
466 } | 462 } |
467 | 463 |
468 void MemoryDumpManager::RequestGlobalDump( | 464 void MemoryDumpManager::RequestGlobalDump( |
469 MemoryDumpType dump_type, | 465 MemoryDumpType dump_type, |
470 MemoryDumpLevelOfDetail level_of_detail) { | 466 MemoryDumpLevelOfDetail level_of_detail) { |
471 RequestGlobalDump(dump_type, level_of_detail, GlobalMemoryDumpCallback()); | 467 auto noop_callback = [](uint64_t dump_guid, bool success) {}; |
| 468 RequestGlobalDump(dump_type, level_of_detail, Bind(noop_callback)); |
472 } | 469 } |
473 | 470 |
474 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( | 471 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( |
475 MemoryDumpProvider* provider) { | 472 MemoryDumpProvider* provider) { |
476 AutoLock lock(lock_); | 473 AutoLock lock(lock_); |
477 | 474 |
478 for (const auto& info : dump_providers_) { | 475 for (const auto& info : dump_providers_) { |
479 if (info->dump_provider == provider) | 476 if (info->dump_provider == provider) |
480 return true; | 477 return true; |
481 } | 478 } |
(...skipping 10 matching lines...) Expand all Loading... |
492 dump_thread_ = MakeUnique<Thread>("MemoryInfra"); | 489 dump_thread_ = MakeUnique<Thread>("MemoryInfra"); |
493 bool started = dump_thread_->Start(); | 490 bool started = dump_thread_->Start(); |
494 CHECK(started); | 491 CHECK(started); |
495 | 492 |
496 return dump_thread_->task_runner(); | 493 return dump_thread_->task_runner(); |
497 } | 494 } |
498 | 495 |
499 void MemoryDumpManager::CreateProcessDump( | 496 void MemoryDumpManager::CreateProcessDump( |
500 const MemoryDumpRequestArgs& args, | 497 const MemoryDumpRequestArgs& args, |
501 const ProcessMemoryDumpCallback& callback) { | 498 const ProcessMemoryDumpCallback& callback) { |
| 499 if (!is_initialized()) { |
| 500 VLOG(1) << "CreateProcessDump() FAIL: MemoryDumpManager is not initialized"; |
| 501 if (!callback.is_null()) { |
| 502 callback.Run(args.dump_guid, false /* success */, |
| 503 Optional<MemoryDumpCallbackResult>()); |
| 504 } |
| 505 return; |
| 506 } |
| 507 |
502 char guid_str[20]; | 508 char guid_str[20]; |
503 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); | 509 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); |
504 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", | 510 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", |
505 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", | 511 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", |
506 TRACE_STR_COPY(guid_str)); | 512 TRACE_STR_COPY(guid_str)); |
507 | 513 |
508 // If argument filter is enabled then only background mode dumps should be | 514 // If argument filter is enabled then only background mode dumps should be |
509 // allowed. In case the trace config passed for background tracing session | 515 // allowed. In case the trace config passed for background tracing session |
510 // missed the allowed modes argument, it crashes here instead of creating | 516 // missed the allowed modes argument, it crashes here instead of creating |
511 // unexpected dumps. | 517 // unexpected dumps. |
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 callback_task_runner->PostTask( | 731 callback_task_runner->PostTask( |
726 FROM_HERE, BindOnce(&MemoryDumpManager::FinalizeDumpAndAddToTrace, | 732 FROM_HERE, BindOnce(&MemoryDumpManager::FinalizeDumpAndAddToTrace, |
727 Unretained(this), Passed(&pmd_async_state))); | 733 Unretained(this), Passed(&pmd_async_state))); |
728 return; | 734 return; |
729 } | 735 } |
730 | 736 |
731 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); | 737 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); |
732 | 738 |
733 // The results struct to fill. | 739 // The results struct to fill. |
734 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 740 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
735 base::Optional<MemoryDumpCallbackResult> result; | 741 Optional<MemoryDumpCallbackResult> result; |
736 | 742 |
737 bool dump_successful = pmd_async_state->dump_successful; | 743 bool dump_successful = pmd_async_state->dump_successful; |
738 | 744 |
739 for (const auto& kv : pmd_async_state->process_dumps) { | 745 for (const auto& kv : pmd_async_state->process_dumps) { |
740 ProcessId pid = kv.first; // kNullProcessId for the current process. | 746 ProcessId pid = kv.first; // kNullProcessId for the current process. |
741 ProcessMemoryDump* process_memory_dump = kv.second.get(); | 747 ProcessMemoryDump* process_memory_dump = kv.second.get(); |
742 | 748 |
743 // SUMMARY_ONLY dumps are just return the summarized result in the | 749 // SUMMARY_ONLY dumps are just return the summarized result in the |
744 // ProcessMemoryDumpCallback. These shouldn't be added to the trace to | 750 // ProcessMemoryDumpCallback. These shouldn't be added to the trace to |
745 // avoid confusing trace consumers. | 751 // avoid confusing trace consumers. |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
855 | 861 |
856 // When peak detection is enabled, trigger a dump straight away as it | 862 // When peak detection is enabled, trigger a dump straight away as it |
857 // gives a good reference point for analyzing the trace. | 863 // gives a good reference point for analyzing the trace. |
858 if (is_coordinator_) { | 864 if (is_coordinator_) { |
859 GetOrCreateBgTaskRunnerLocked()->PostTask( | 865 GetOrCreateBgTaskRunnerLocked()->PostTask( |
860 FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail)); | 866 FROM_HERE, BindRepeating(&OnPeakDetected, trigger.level_of_detail)); |
861 } | 867 } |
862 } | 868 } |
863 } | 869 } |
864 | 870 |
865 // Only coordinator process triggers periodic global memory dumps. | 871 // Only coordinator process triggers periodic memory dumps. |
866 if (is_coordinator_ && !periodic_config.triggers.empty()) { | 872 if (is_coordinator_ && !periodic_config.triggers.empty()) { |
867 MemoryDumpScheduler::GetInstance()->Start(periodic_config, | 873 MemoryDumpScheduler::GetInstance()->Start(periodic_config, |
868 GetOrCreateBgTaskRunnerLocked()); | 874 GetOrCreateBgTaskRunnerLocked()); |
869 } | 875 } |
870 } | 876 } |
871 | 877 |
872 void MemoryDumpManager::TeardownForTracing() { | 878 void MemoryDumpManager::TeardownForTracing() { |
873 // There might be a memory dump in progress while this happens. Therefore, | 879 // There might be a memory dump in progress while this happens. Therefore, |
874 // ensure that the MDM state which depends on the tracing enabled / disabled | 880 // ensure that the MDM state which depends on the tracing enabled / disabled |
875 // state is always accessed by the dumping methods holding the |lock_|. | 881 // state is always accessed by the dumping methods holding the |lock_|. |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
908 if (iter == process_dumps.end()) { | 914 if (iter == process_dumps.end()) { |
909 std::unique_ptr<ProcessMemoryDump> new_pmd( | 915 std::unique_ptr<ProcessMemoryDump> new_pmd( |
910 new ProcessMemoryDump(heap_profiler_serialization_state, dump_args)); | 916 new ProcessMemoryDump(heap_profiler_serialization_state, dump_args)); |
911 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 917 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
912 } | 918 } |
913 return iter->second.get(); | 919 return iter->second.get(); |
914 } | 920 } |
915 | 921 |
916 } // namespace trace_event | 922 } // namespace trace_event |
917 } // namespace base | 923 } // namespace base |
OLD | NEW |