| 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 |