Chromium Code Reviews| 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 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 75 "cc::SoftwareImageDecodeCache", | 75 "cc::SoftwareImageDecodeCache", |
| 76 "cc::StagingBufferPool", | 76 "cc::StagingBufferPool", |
| 77 "gpu::BufferManager", | 77 "gpu::BufferManager", |
| 78 "gpu::MappedMemoryManager", | 78 "gpu::MappedMemoryManager", |
| 79 "gpu::RenderbufferManager", | 79 "gpu::RenderbufferManager", |
| 80 "BlacklistTestDumpProvider" // for testing | 80 "BlacklistTestDumpProvider" // for testing |
| 81 }; | 81 }; |
| 82 | 82 |
| 83 // Callback wrapper to hook upon the completion of RequestGlobalDump() and | 83 // Callback wrapper to hook upon the completion of RequestGlobalDump() and |
| 84 // inject trace markers. | 84 // inject trace markers. |
| 85 void OnGlobalDumpDone(MemoryDumpCallback wrapped_callback, | 85 void OnGlobalDumpDone(GlobalMemoryDumpCallback wrapped_callback, |
| 86 uint64_t dump_guid, | 86 uint64_t dump_guid, |
| 87 bool success) { | 87 bool success) { |
| 88 char guid_str[20]; | 88 char guid_str[20]; |
| 89 sprintf(guid_str, "0x%" PRIx64, dump_guid); | 89 sprintf(guid_str, "0x%" PRIx64, dump_guid); |
| 90 TRACE_EVENT_NESTABLE_ASYNC_END2(MemoryDumpManager::kTraceCategory, | 90 TRACE_EVENT_NESTABLE_ASYNC_END2(MemoryDumpManager::kTraceCategory, |
| 91 "GlobalMemoryDump", TRACE_ID_LOCAL(dump_guid), | 91 "GlobalMemoryDump", TRACE_ID_LOCAL(dump_guid), |
| 92 "dump_guid", TRACE_STR_COPY(guid_str), | 92 "dump_guid", TRACE_STR_COPY(guid_str), |
| 93 "success", success); | 93 "success", success); |
| 94 | 94 |
| 95 if (!wrapped_callback.is_null()) { | 95 if (!wrapped_callback.is_null()) { |
| (...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 443 | 443 |
| 444 AutoLock lock(lock_); | 444 AutoLock lock(lock_); |
| 445 dump_providers_for_polling_.erase(mdpinfo); | 445 dump_providers_for_polling_.erase(mdpinfo); |
| 446 DCHECK(!dump_providers_for_polling_.empty()) | 446 DCHECK(!dump_providers_for_polling_.empty()) |
| 447 << "All polling MDPs cannot be unregistered."; | 447 << "All polling MDPs cannot be unregistered."; |
| 448 } | 448 } |
| 449 | 449 |
| 450 void MemoryDumpManager::RequestGlobalDump( | 450 void MemoryDumpManager::RequestGlobalDump( |
| 451 MemoryDumpType dump_type, | 451 MemoryDumpType dump_type, |
| 452 MemoryDumpLevelOfDetail level_of_detail, | 452 MemoryDumpLevelOfDetail level_of_detail, |
| 453 const MemoryDumpCallback& callback) { | 453 const GlobalMemoryDumpCallback& callback) { |
| 454 // Bail out immediately if tracing is not enabled at all or if the dump mode | 454 // Bail out immediately if tracing is not enabled at all or if the dump mode |
| 455 // is not allowed. | 455 // is not allowed. |
| 456 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) || | 456 if (!UNLIKELY(subtle::NoBarrier_Load(&memory_tracing_enabled_)) || |
| 457 !IsDumpModeAllowed(level_of_detail)) { | 457 !IsDumpModeAllowed(level_of_detail)) { |
| 458 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory | 458 VLOG(1) << kLogPrefix << " failed because " << kTraceCategory |
| 459 << " tracing category is not enabled or the requested dump mode is " | 459 << " tracing category is not enabled or the requested dump mode is " |
| 460 "not allowed by trace config."; | 460 "not allowed by trace config."; |
| 461 if (!callback.is_null()) | 461 if (!callback.is_null()) |
| 462 callback.Run(0u /* guid */, false /* success */); | 462 callback.Run(0u /* guid */, false /* success */); |
| 463 return; | 463 return; |
| 464 } | 464 } |
| 465 | 465 |
| 466 const uint64_t guid = | 466 const uint64_t guid = |
| 467 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); | 467 TraceLog::GetInstance()->MangleEventId(g_next_guid.GetNext()); |
| 468 | 468 |
| 469 // Creates an async event to keep track of the global dump evolution. | 469 // Creates an async event to keep track of the global dump evolution. |
| 470 // The |wrapped_callback| will generate the ASYNC_END event and then invoke | 470 // The |wrapped_callback| will generate the ASYNC_END event and then invoke |
| 471 // the real |callback| provided by the caller. | 471 // the real |callback| provided by the caller. |
| 472 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( | 472 TRACE_EVENT_NESTABLE_ASYNC_BEGIN2( |
| 473 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", | 473 kTraceCategory, "GlobalMemoryDump", TRACE_ID_LOCAL(guid), "dump_type", |
| 474 MemoryDumpTypeToString(dump_type), "level_of_detail", | 474 MemoryDumpTypeToString(dump_type), "level_of_detail", |
| 475 MemoryDumpLevelOfDetailToString(level_of_detail)); | 475 MemoryDumpLevelOfDetailToString(level_of_detail)); |
| 476 MemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); | 476 GlobalMemoryDumpCallback wrapped_callback = Bind(&OnGlobalDumpDone, callback); |
| 477 | 477 |
| 478 // The delegate will coordinate the IPC broadcast and at some point invoke | 478 // The delegate will coordinate the IPC broadcast and at some point invoke |
| 479 // CreateProcessDump() to get a dump for the current process. | 479 // CreateProcessDump() to get a dump for the current process. |
| 480 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; | 480 MemoryDumpRequestArgs args = {guid, dump_type, level_of_detail}; |
| 481 delegate_->RequestGlobalMemoryDump(args, wrapped_callback); | 481 delegate_->RequestGlobalMemoryDump(args, wrapped_callback); |
| 482 } | 482 } |
| 483 | 483 |
| 484 void MemoryDumpManager::RequestGlobalDump( | 484 void MemoryDumpManager::RequestGlobalDump( |
| 485 MemoryDumpType dump_type, | 485 MemoryDumpType dump_type, |
| 486 MemoryDumpLevelOfDetail level_of_detail) { | 486 MemoryDumpLevelOfDetail level_of_detail) { |
| 487 RequestGlobalDump(dump_type, level_of_detail, MemoryDumpCallback()); | 487 RequestGlobalDump(dump_type, level_of_detail, GlobalMemoryDumpCallback()); |
| 488 } | 488 } |
| 489 | 489 |
| 490 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( | 490 bool MemoryDumpManager::IsDumpProviderRegisteredForTesting( |
| 491 MemoryDumpProvider* provider) { | 491 MemoryDumpProvider* provider) { |
| 492 AutoLock lock(lock_); | 492 AutoLock lock(lock_); |
| 493 | 493 |
| 494 for (const auto& info : dump_providers_) { | 494 for (const auto& info : dump_providers_) { |
| 495 if (info->dump_provider == provider) | 495 if (info->dump_provider == provider) |
| 496 return true; | 496 return true; |
| 497 } | 497 } |
| 498 return false; | 498 return false; |
| 499 } | 499 } |
| 500 | 500 |
| 501 void MemoryDumpManager::CreateProcessDump(const MemoryDumpRequestArgs& args, | 501 void MemoryDumpManager::CreateProcessDump( |
| 502 const MemoryDumpCallback& callback) { | 502 const MemoryDumpRequestArgs& args, |
| 503 const ProcessMemoryDumpCallback& callback) { | |
| 503 char guid_str[20]; | 504 char guid_str[20]; |
| 504 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); | 505 sprintf(guid_str, "0x%" PRIx64, args.dump_guid); |
| 505 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", | 506 TRACE_EVENT_NESTABLE_ASYNC_BEGIN1(kTraceCategory, "ProcessMemoryDump", |
| 506 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", | 507 TRACE_ID_LOCAL(args.dump_guid), "dump_guid", |
| 507 TRACE_STR_COPY(guid_str)); | 508 TRACE_STR_COPY(guid_str)); |
| 508 | 509 |
| 509 // If argument filter is enabled then only background mode dumps should be | 510 // If argument filter is enabled then only background mode dumps should be |
| 510 // allowed. In case the trace config passed for background tracing session | 511 // allowed. In case the trace config passed for background tracing session |
| 511 // missed the allowed modes argument, it crashes here instead of creating | 512 // missed the allowed modes argument, it crashes here instead of creating |
| 512 // unexpected dumps. | 513 // unexpected dumps. |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 755 callback_task_runner->PostTask( | 756 callback_task_runner->PostTask( |
| 756 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, | 757 FROM_HERE, Bind(&MemoryDumpManager::FinalizeDumpAndAddToTrace, |
| 757 Passed(&pmd_async_state))); | 758 Passed(&pmd_async_state))); |
| 758 return; | 759 return; |
| 759 } | 760 } |
| 760 | 761 |
| 761 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); | 762 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); |
| 762 | 763 |
| 763 // The results struct to fill. | 764 // The results struct to fill. |
| 764 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 765 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
| 765 MemoryDumpCallbackResult result; | 766 base::Optional<MemoryDumpCallbackResult> result_opt; |
|
hjd
2017/04/06 11:18:45
Should we have #include "base/optional.h"?
Primiano Tucci (use gerrit)
2017/04/07 15:31:36
+1, IWYU (Include What You Use, i.e. don't depen d
fmeawad
2017/04/10 20:20:19
Done.
| |
| 766 | 767 |
| 767 for (const auto& kv : pmd_async_state->process_dumps) { | 768 for (const auto& kv : pmd_async_state->process_dumps) { |
| 768 ProcessId pid = kv.first; // kNullProcessId for the current process. | 769 ProcessId pid = kv.first; // kNullProcessId for the current process. |
| 769 ProcessMemoryDump* process_memory_dump = kv.second.get(); | 770 ProcessMemoryDump* process_memory_dump = kv.second.get(); |
| 770 std::unique_ptr<TracedValue> traced_value(new TracedValue); | 771 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
| 771 process_memory_dump->AsValueInto(traced_value.get()); | 772 process_memory_dump->AsValueInto(traced_value.get()); |
| 772 traced_value->SetString("level_of_detail", | 773 traced_value->SetString("level_of_detail", |
| 773 MemoryDumpLevelOfDetailToString( | 774 MemoryDumpLevelOfDetailToString( |
| 774 pmd_async_state->req_args.level_of_detail)); | 775 pmd_async_state->req_args.level_of_detail)); |
| 775 const char* const event_name = | 776 const char* const event_name = |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 787 | 788 |
| 788 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 789 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
| 789 // Don't try to fill the struct in detailed mode since it is hard to avoid | 790 // Don't try to fill the struct in detailed mode since it is hard to avoid |
| 790 // double counting. | 791 // double counting. |
| 791 if (pmd_async_state->req_args.level_of_detail == | 792 if (pmd_async_state->req_args.level_of_detail == |
| 792 MemoryDumpLevelOfDetail::DETAILED) | 793 MemoryDumpLevelOfDetail::DETAILED) |
| 793 continue; | 794 continue; |
| 794 | 795 |
| 795 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 796 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
| 796 if (pid == kNullProcessId) { | 797 if (pid == kNullProcessId) { |
| 798 MemoryDumpCallbackResult result; | |
| 797 result.chrome_dump.malloc_total_kb = | 799 result.chrome_dump.malloc_total_kb = |
| 798 GetDumpsSumKb("malloc", process_memory_dump); | 800 GetDumpsSumKb("malloc", process_memory_dump); |
| 799 result.chrome_dump.v8_total_kb = | 801 result.chrome_dump.v8_total_kb = |
| 800 GetDumpsSumKb("v8/*", process_memory_dump); | 802 GetDumpsSumKb("v8/*", process_memory_dump); |
| 801 | 803 |
| 802 // partition_alloc reports sizes for both allocated_objects and | 804 // partition_alloc reports sizes for both allocated_objects and |
| 803 // partitions. The memory allocated_objects uses is a subset of | 805 // partitions. The memory allocated_objects uses is a subset of |
| 804 // the partitions memory so to avoid double counting we only | 806 // the partitions memory so to avoid double counting we only |
| 805 // count partitions memory. | 807 // count partitions memory. |
| 806 result.chrome_dump.partition_alloc_total_kb = | 808 result.chrome_dump.partition_alloc_total_kb = |
| 807 GetDumpsSumKb("partition_alloc/partitions/*", process_memory_dump); | 809 GetDumpsSumKb("partition_alloc/partitions/*", process_memory_dump); |
| 808 result.chrome_dump.blink_gc_total_kb = | 810 result.chrome_dump.blink_gc_total_kb = |
| 809 GetDumpsSumKb("blink_gc", process_memory_dump); | 811 GetDumpsSumKb("blink_gc", process_memory_dump); |
| 812 result_opt = result; | |
| 810 } | 813 } |
| 811 } | 814 } |
| 812 | 815 |
| 813 bool tracing_still_enabled; | 816 bool tracing_still_enabled; |
| 814 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &tracing_still_enabled); | 817 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &tracing_still_enabled); |
| 815 if (!tracing_still_enabled) { | 818 if (!tracing_still_enabled) { |
| 816 pmd_async_state->dump_successful = false; | 819 pmd_async_state->dump_successful = false; |
| 817 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" | 820 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" |
| 818 << " the dump was completed"; | 821 << " the dump was completed"; |
| 819 } | 822 } |
| 820 | 823 |
| 821 if (!pmd_async_state->callback.is_null()) { | 824 if (!pmd_async_state->callback.is_null()) { |
| 822 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful); | 825 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful, |
| 826 result_opt); | |
| 823 pmd_async_state->callback.Reset(); | 827 pmd_async_state->callback.Reset(); |
| 824 } | 828 } |
| 825 | 829 |
| 826 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", | 830 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", |
| 827 TRACE_ID_LOCAL(dump_guid)); | 831 TRACE_ID_LOCAL(dump_guid)); |
| 828 } | 832 } |
| 829 | 833 |
| 830 void MemoryDumpManager::OnTraceLogEnabled() { | 834 void MemoryDumpManager::OnTraceLogEnabled() { |
| 831 bool enabled; | 835 bool enabled; |
| 832 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); | 836 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 953 AutoLock lock(lock_); | 957 AutoLock lock(lock_); |
| 954 if (!session_state_) | 958 if (!session_state_) |
| 955 return false; | 959 return false; |
| 956 return session_state_->IsDumpModeAllowed(dump_mode); | 960 return session_state_->IsDumpModeAllowed(dump_mode); |
| 957 } | 961 } |
| 958 | 962 |
| 959 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( | 963 MemoryDumpManager::ProcessMemoryDumpAsyncState::ProcessMemoryDumpAsyncState( |
| 960 MemoryDumpRequestArgs req_args, | 964 MemoryDumpRequestArgs req_args, |
| 961 const MemoryDumpProviderInfo::OrderedSet& dump_providers, | 965 const MemoryDumpProviderInfo::OrderedSet& dump_providers, |
| 962 scoped_refptr<MemoryDumpSessionState> session_state, | 966 scoped_refptr<MemoryDumpSessionState> session_state, |
| 963 MemoryDumpCallback callback, | 967 ProcessMemoryDumpCallback callback, |
| 964 scoped_refptr<SingleThreadTaskRunner> dump_thread_task_runner) | 968 scoped_refptr<SingleThreadTaskRunner> dump_thread_task_runner) |
| 965 : req_args(req_args), | 969 : req_args(req_args), |
| 966 session_state(std::move(session_state)), | 970 session_state(std::move(session_state)), |
| 967 callback(callback), | 971 callback(callback), |
| 968 dump_successful(true), | 972 dump_successful(true), |
| 969 callback_task_runner(ThreadTaskRunnerHandle::Get()), | 973 callback_task_runner(ThreadTaskRunnerHandle::Get()), |
| 970 dump_thread_task_runner(std::move(dump_thread_task_runner)) { | 974 dump_thread_task_runner(std::move(dump_thread_task_runner)) { |
| 971 pending_dump_providers.reserve(dump_providers.size()); | 975 pending_dump_providers.reserve(dump_providers.size()); |
| 972 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); | 976 pending_dump_providers.assign(dump_providers.rbegin(), dump_providers.rend()); |
| 973 } | 977 } |
| 974 | 978 |
| 975 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { | 979 MemoryDumpManager::ProcessMemoryDumpAsyncState::~ProcessMemoryDumpAsyncState() { |
| 976 } | 980 } |
| 977 | 981 |
| 978 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: | 982 ProcessMemoryDump* MemoryDumpManager::ProcessMemoryDumpAsyncState:: |
| 979 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid, | 983 GetOrCreateMemoryDumpContainerForProcess(ProcessId pid, |
| 980 const MemoryDumpArgs& dump_args) { | 984 const MemoryDumpArgs& dump_args) { |
| 981 auto iter = process_dumps.find(pid); | 985 auto iter = process_dumps.find(pid); |
| 982 if (iter == process_dumps.end()) { | 986 if (iter == process_dumps.end()) { |
| 983 std::unique_ptr<ProcessMemoryDump> new_pmd( | 987 std::unique_ptr<ProcessMemoryDump> new_pmd( |
| 984 new ProcessMemoryDump(session_state, dump_args)); | 988 new ProcessMemoryDump(session_state, dump_args)); |
| 985 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 989 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
| 986 } | 990 } |
| 987 return iter->second.get(); | 991 return iter->second.get(); |
| 988 } | 992 } |
| 989 | 993 |
| 990 } // namespace trace_event | 994 } // namespace trace_event |
| 991 } // namespace base | 995 } // namespace base |
| OLD | NEW |