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 18 matching lines...) Expand all Loading... |
29 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 29 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
30 #include "base/trace_event/heap_profiler_event_filter.h" | 30 #include "base/trace_event/heap_profiler_event_filter.h" |
31 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 31 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
32 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" | 32 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
33 #include "base/trace_event/malloc_dump_provider.h" | 33 #include "base/trace_event/malloc_dump_provider.h" |
34 #include "base/trace_event/memory_dump_provider.h" | 34 #include "base/trace_event/memory_dump_provider.h" |
35 #include "base/trace_event/memory_dump_scheduler.h" | 35 #include "base/trace_event/memory_dump_scheduler.h" |
36 #include "base/trace_event/memory_dump_session_state.h" | 36 #include "base/trace_event/memory_dump_session_state.h" |
37 #include "base/trace_event/memory_infra_background_whitelist.h" | 37 #include "base/trace_event/memory_infra_background_whitelist.h" |
38 #include "base/trace_event/memory_peak_detector.h" | 38 #include "base/trace_event/memory_peak_detector.h" |
| 39 #include "base/trace_event/memory_tracing_observer.h" |
39 #include "base/trace_event/process_memory_dump.h" | 40 #include "base/trace_event/process_memory_dump.h" |
40 #include "base/trace_event/trace_event.h" | 41 #include "base/trace_event/trace_event.h" |
41 #include "base/trace_event/trace_event_argument.h" | 42 #include "base/trace_event/trace_event_argument.h" |
42 #include "build/build_config.h" | 43 #include "build/build_config.h" |
43 | 44 |
44 #if defined(OS_ANDROID) | 45 #if defined(OS_ANDROID) |
45 #include "base/trace_event/java_heap_dump_provider_android.h" | 46 #include "base/trace_event/java_heap_dump_provider_android.h" |
46 #endif | 47 #endif |
47 | 48 |
48 namespace base { | 49 namespace base { |
49 namespace trace_event { | 50 namespace trace_event { |
50 | 51 |
51 namespace { | 52 namespace { |
52 | 53 |
53 const int kTraceEventNumArgs = 1; | |
54 const char* kTraceEventArgNames[] = {"dumps"}; | |
55 const unsigned char kTraceEventArgTypes[] = {TRACE_VALUE_TYPE_CONVERTABLE}; | |
56 | |
57 StaticAtomicSequenceNumber g_next_guid; | 54 StaticAtomicSequenceNumber g_next_guid; |
58 MemoryDumpManager* g_instance_for_testing = nullptr; | 55 MemoryDumpManager* g_instance_for_testing = nullptr; |
59 | 56 |
60 // The list of names of dump providers that are blacklisted from strict thread | 57 // The list of names of dump providers that are blacklisted from strict thread |
61 // affinity check on unregistration. These providers could potentially cause | 58 // affinity check on unregistration. These providers could potentially cause |
62 // crashes on build bots if they do not unregister on right thread. | 59 // crashes on build bots if they do not unregister on right thread. |
63 // TODO(ssid): Fix all the dump providers to unregister if needed and clear the | 60 // TODO(ssid): Fix all the dump providers to unregister if needed and clear the |
64 // blacklist, crbug.com/643438. | 61 // blacklist, crbug.com/643438. |
65 const char* const kStrictThreadCheckBlacklist[] = { | 62 const char* const kStrictThreadCheckBlacklist[] = { |
66 "ClientDiscardableSharedMemoryManager", | 63 "ClientDiscardableSharedMemoryManager", |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 | 189 |
193 // At this point the command line may not be initialized but we try to | 190 // At this point the command line may not be initialized but we try to |
194 // enable the heap profiler to capture allocations as soon as possible. | 191 // enable the heap profiler to capture allocations as soon as possible. |
195 EnableHeapProfilingIfNeeded(); | 192 EnableHeapProfilingIfNeeded(); |
196 | 193 |
197 strict_thread_check_blacklist_.insert(std::begin(kStrictThreadCheckBlacklist), | 194 strict_thread_check_blacklist_.insert(std::begin(kStrictThreadCheckBlacklist), |
198 std::end(kStrictThreadCheckBlacklist)); | 195 std::end(kStrictThreadCheckBlacklist)); |
199 } | 196 } |
200 | 197 |
201 MemoryDumpManager::~MemoryDumpManager() { | 198 MemoryDumpManager::~MemoryDumpManager() { |
202 TraceLog::GetInstance()->RemoveEnabledStateObserver(this); | |
203 } | 199 } |
204 | 200 |
205 void MemoryDumpManager::EnableHeapProfilingIfNeeded() { | 201 void MemoryDumpManager::EnableHeapProfilingIfNeeded() { |
206 if (heap_profiling_enabled_) | 202 if (heap_profiling_enabled_) |
207 return; | 203 return; |
208 | 204 |
209 if (!CommandLine::InitializedForCurrentProcess() || | 205 if (!CommandLine::InitializedForCurrentProcess() || |
210 !CommandLine::ForCurrentProcess()->HasSwitch( | 206 !CommandLine::ForCurrentProcess()->HasSwitch( |
211 switches::kEnableHeapProfiling)) | 207 switches::kEnableHeapProfiling)) |
212 return; | 208 return; |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 | 279 |
284 TraceConfig::EventFilters filters; | 280 TraceConfig::EventFilters filters; |
285 filters.push_back(heap_profiler_filter_config); | 281 filters.push_back(heap_profiler_filter_config); |
286 TraceConfig filtering_trace_config; | 282 TraceConfig filtering_trace_config; |
287 filtering_trace_config.SetEventFilters(filters); | 283 filtering_trace_config.SetEventFilters(filters); |
288 | 284 |
289 TraceLog::GetInstance()->SetEnabled(filtering_trace_config, | 285 TraceLog::GetInstance()->SetEnabled(filtering_trace_config, |
290 TraceLog::FILTERING_MODE); | 286 TraceLog::FILTERING_MODE); |
291 } | 287 } |
292 | 288 |
293 // If tracing was enabled before initializing MemoryDumpManager, we missed the | 289 // TODO(hjd): Move out of MDM. See: crbug.com/703184 |
294 // OnTraceLogEnabled() event. Synthetize it so we can late-join the party. | 290 tracing_observer_ = |
295 // IsEnabled is called before adding observer to avoid calling | 291 MakeUnique<MemoryTracingObserver>(TraceLog::GetInstance(), this); |
296 // OnTraceLogEnabled twice. | |
297 bool is_tracing_already_enabled = TraceLog::GetInstance()->IsEnabled(); | |
298 TraceLog::GetInstance()->AddEnabledStateObserver(this); | |
299 if (is_tracing_already_enabled) | |
300 OnTraceLogEnabled(); | |
301 } | 292 } |
302 | 293 |
303 void MemoryDumpManager::RegisterDumpProvider( | 294 void MemoryDumpManager::RegisterDumpProvider( |
304 MemoryDumpProvider* mdp, | 295 MemoryDumpProvider* mdp, |
305 const char* name, | 296 const char* name, |
306 scoped_refptr<SingleThreadTaskRunner> task_runner, | 297 scoped_refptr<SingleThreadTaskRunner> task_runner, |
307 MemoryDumpProvider::Options options) { | 298 MemoryDumpProvider::Options options) { |
308 options.dumps_on_single_thread_task_runner = true; | 299 options.dumps_on_single_thread_task_runner = true; |
309 RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options); | 300 RegisterDumpProviderInternal(mdp, name, std::move(task_runner), options); |
310 } | 301 } |
(...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
716 const ProcessMemoryDump* pmd) { | 707 const ProcessMemoryDump* pmd) { |
717 uint64_t sum = 0; | 708 uint64_t sum = 0; |
718 for (const auto& kv : pmd->allocator_dumps()) { | 709 for (const auto& kv : pmd->allocator_dumps()) { |
719 auto name = StringPiece(kv.first); | 710 auto name = StringPiece(kv.first); |
720 if (MatchPattern(name, pattern)) | 711 if (MatchPattern(name, pattern)) |
721 sum += kv.second->GetSize(); | 712 sum += kv.second->GetSize(); |
722 } | 713 } |
723 return sum / 1024; | 714 return sum / 1024; |
724 } | 715 } |
725 | 716 |
726 // static | |
727 void MemoryDumpManager::FinalizeDumpAndAddToTrace( | 717 void MemoryDumpManager::FinalizeDumpAndAddToTrace( |
728 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { | 718 std::unique_ptr<ProcessMemoryDumpAsyncState> pmd_async_state) { |
729 HEAP_PROFILER_SCOPED_IGNORE; | 719 HEAP_PROFILER_SCOPED_IGNORE; |
730 DCHECK(pmd_async_state->pending_dump_providers.empty()); | 720 DCHECK(pmd_async_state->pending_dump_providers.empty()); |
731 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; | 721 const uint64_t dump_guid = pmd_async_state->req_args.dump_guid; |
732 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { | 722 if (!pmd_async_state->callback_task_runner->BelongsToCurrentThread()) { |
733 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = | 723 scoped_refptr<SingleThreadTaskRunner> callback_task_runner = |
734 pmd_async_state->callback_task_runner; | 724 pmd_async_state->callback_task_runner; |
735 callback_task_runner->PostTask( | 725 callback_task_runner->PostTask( |
736 FROM_HERE, BindOnce(&MemoryDumpManager::FinalizeDumpAndAddToTrace, | 726 FROM_HERE, BindOnce(&MemoryDumpManager::FinalizeDumpAndAddToTrace, |
737 Passed(&pmd_async_state))); | 727 Unretained(this), Passed(&pmd_async_state))); |
738 return; | 728 return; |
739 } | 729 } |
740 | 730 |
741 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); | 731 TRACE_EVENT0(kTraceCategory, "MemoryDumpManager::FinalizeDumpAndAddToTrace"); |
742 | 732 |
743 // The results struct to fill. | 733 // The results struct to fill. |
744 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 734 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
745 base::Optional<MemoryDumpCallbackResult> result; | 735 base::Optional<MemoryDumpCallbackResult> result; |
| 736 |
| 737 bool dump_successful = pmd_async_state->dump_successful; |
| 738 |
746 for (const auto& kv : pmd_async_state->process_dumps) { | 739 for (const auto& kv : pmd_async_state->process_dumps) { |
747 ProcessId pid = kv.first; // kNullProcessId for the current process. | 740 ProcessId pid = kv.first; // kNullProcessId for the current process. |
748 ProcessMemoryDump* process_memory_dump = kv.second.get(); | 741 ProcessMemoryDump* process_memory_dump = kv.second.get(); |
749 std::unique_ptr<TracedValue> traced_value(new TracedValue); | |
750 process_memory_dump->AsValueInto(traced_value.get()); | |
751 traced_value->SetString("level_of_detail", | |
752 MemoryDumpLevelOfDetailToString( | |
753 pmd_async_state->req_args.level_of_detail)); | |
754 const char* const event_name = | |
755 MemoryDumpTypeToString(pmd_async_state->req_args.dump_type); | |
756 | 742 |
757 std::unique_ptr<ConvertableToTraceFormat> event_value( | 743 bool added_to_trace = tracing_observer_->AddDumpToTraceIfEnabled( |
758 std::move(traced_value)); | 744 &pmd_async_state->req_args, pid, process_memory_dump); |
759 TRACE_EVENT_API_ADD_TRACE_EVENT_WITH_PROCESS_ID( | 745 |
760 TRACE_EVENT_PHASE_MEMORY_DUMP, | 746 dump_successful = dump_successful && added_to_trace; |
761 TraceLog::GetCategoryGroupEnabled(kTraceCategory), event_name, | |
762 trace_event_internal::kGlobalScope, dump_guid, pid, | |
763 kTraceEventNumArgs, kTraceEventArgNames, | |
764 kTraceEventArgTypes, nullptr /* arg_values */, &event_value, | |
765 TRACE_EVENT_FLAG_HAS_ID); | |
766 | 747 |
767 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 748 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
768 // Don't try to fill the struct in detailed mode since it is hard to avoid | 749 // Don't try to fill the struct in detailed mode since it is hard to avoid |
769 // double counting. | 750 // double counting. |
770 if (pmd_async_state->req_args.level_of_detail == | 751 if (pmd_async_state->req_args.level_of_detail == |
771 MemoryDumpLevelOfDetail::DETAILED) | 752 MemoryDumpLevelOfDetail::DETAILED) |
772 continue; | 753 continue; |
773 if (!result.has_value()) | 754 if (!result.has_value()) |
774 result = MemoryDumpCallbackResult(); | 755 result = MemoryDumpCallbackResult(); |
775 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 | 756 // TODO(hjd): Transitional until we send the full PMD. See crbug.com/704203 |
(...skipping 11 matching lines...) Expand all Loading... |
787 GetDumpsSumKb("partition_alloc/partitions/*", process_memory_dump); | 768 GetDumpsSumKb("partition_alloc/partitions/*", process_memory_dump); |
788 result->chrome_dump.blink_gc_total_kb = | 769 result->chrome_dump.blink_gc_total_kb = |
789 GetDumpsSumKb("blink_gc", process_memory_dump); | 770 GetDumpsSumKb("blink_gc", process_memory_dump); |
790 FillOsDumpFromProcessMemoryDump(process_memory_dump, &result->os_dump); | 771 FillOsDumpFromProcessMemoryDump(process_memory_dump, &result->os_dump); |
791 } else { | 772 } else { |
792 auto& os_dump = result->extra_processes_dump[pid]; | 773 auto& os_dump = result->extra_processes_dump[pid]; |
793 FillOsDumpFromProcessMemoryDump(process_memory_dump, &os_dump); | 774 FillOsDumpFromProcessMemoryDump(process_memory_dump, &os_dump); |
794 } | 775 } |
795 } | 776 } |
796 | 777 |
797 bool tracing_still_enabled; | |
798 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &tracing_still_enabled); | |
799 if (!tracing_still_enabled) { | |
800 pmd_async_state->dump_successful = false; | |
801 VLOG(1) << kLogPrefix << " failed because tracing was disabled before" | |
802 << " the dump was completed"; | |
803 } | |
804 | |
805 if (!pmd_async_state->callback.is_null()) { | 778 if (!pmd_async_state->callback.is_null()) { |
806 pmd_async_state->callback.Run(dump_guid, pmd_async_state->dump_successful, | 779 pmd_async_state->callback.Run(dump_guid, dump_successful, result); |
807 result); | |
808 pmd_async_state->callback.Reset(); | 780 pmd_async_state->callback.Reset(); |
809 } | 781 } |
810 | 782 |
811 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", | 783 TRACE_EVENT_NESTABLE_ASYNC_END0(kTraceCategory, "ProcessMemoryDump", |
812 TRACE_ID_LOCAL(dump_guid)); | 784 TRACE_ID_LOCAL(dump_guid)); |
813 } | 785 } |
814 | 786 |
815 void MemoryDumpManager::OnTraceLogEnabled() { | 787 void MemoryDumpManager::Enable( |
816 bool enabled; | 788 const TraceConfig::MemoryDumpConfig& memory_dump_config) { |
817 TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategory, &enabled); | |
818 if (!enabled) | |
819 return; | |
820 | |
821 // Initialize the TraceLog for the current thread. This is to avoid that the | |
822 // TraceLog memory dump provider is registered lazily in the PostTask() below | |
823 // while the |lock_| is taken; | |
824 TraceLog::GetInstance()->InitializeThreadLocalEventBufferIfSupported(); | |
825 | |
826 // Spin-up the thread used to invoke unbound dump providers. | 789 // Spin-up the thread used to invoke unbound dump providers. |
827 std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra")); | 790 std::unique_ptr<Thread> dump_thread(new Thread("MemoryInfra")); |
828 if (!dump_thread->Start()) { | 791 if (!dump_thread->Start()) { |
829 LOG(ERROR) << "Failed to start the memory-infra thread for tracing"; | 792 LOG(ERROR) << "Failed to start the memory-infra thread for tracing"; |
830 return; | 793 return; |
831 } | 794 } |
832 | 795 |
833 const TraceConfig& trace_config = | |
834 TraceLog::GetInstance()->GetCurrentTraceConfig(); | |
835 const TraceConfig::MemoryDumpConfig& memory_dump_config = | |
836 trace_config.memory_dump_config(); | |
837 scoped_refptr<MemoryDumpSessionState> session_state = | 796 scoped_refptr<MemoryDumpSessionState> session_state = |
838 new MemoryDumpSessionState; | 797 new MemoryDumpSessionState; |
839 session_state->SetAllowedDumpModes(memory_dump_config.allowed_dump_modes); | 798 session_state->SetAllowedDumpModes(memory_dump_config.allowed_dump_modes); |
840 session_state->set_heap_profiler_breakdown_threshold_bytes( | 799 session_state->set_heap_profiler_breakdown_threshold_bytes( |
841 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); | 800 memory_dump_config.heap_profiler_options.breakdown_threshold_bytes); |
842 if (heap_profiling_enabled_) { | 801 if (heap_profiling_enabled_) { |
843 // If heap profiling is enabled, the stack frame deduplicator and type name | 802 // If heap profiling is enabled, the stack frame deduplicator and type name |
844 // deduplicator will be in use. Add a metadata events to write the frames | 803 // deduplicator will be in use. Add a metadata events to write the frames |
845 // and type IDs. | 804 // and type IDs. |
846 session_state->SetStackFrameDeduplicator( | 805 session_state->SetStackFrameDeduplicator( |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 } | 870 } |
912 } | 871 } |
913 | 872 |
914 // Only coordinator process triggers periodic global memory dumps. | 873 // Only coordinator process triggers periodic global memory dumps. |
915 if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) { | 874 if (delegate_->IsCoordinator() && !periodic_config.triggers.empty()) { |
916 MemoryDumpScheduler::GetInstance()->Start(periodic_config, | 875 MemoryDumpScheduler::GetInstance()->Start(periodic_config, |
917 dump_thread_->task_runner()); | 876 dump_thread_->task_runner()); |
918 } | 877 } |
919 } | 878 } |
920 | 879 |
921 void MemoryDumpManager::OnTraceLogDisabled() { | 880 void MemoryDumpManager::Disable() { |
922 // There might be a memory dump in progress while this happens. Therefore, | 881 // There might be a memory dump in progress while this happens. Therefore, |
923 // ensure that the MDM state which depends on the tracing enabled / disabled | 882 // ensure that the MDM state which depends on the tracing enabled / disabled |
924 // state is always accessed by the dumping methods holding the |lock_|. | 883 // state is always accessed by the dumping methods holding the |lock_|. |
925 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) | 884 if (!subtle::NoBarrier_Load(&memory_tracing_enabled_)) |
926 return; | 885 return; |
927 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); | 886 subtle::NoBarrier_Store(&memory_tracing_enabled_, 0); |
928 std::unique_ptr<Thread> dump_thread; | 887 std::unique_ptr<Thread> dump_thread; |
929 { | 888 { |
930 AutoLock lock(lock_); | 889 AutoLock lock(lock_); |
931 MemoryDumpScheduler::GetInstance()->Stop(); | 890 MemoryDumpScheduler::GetInstance()->Stop(); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
973 if (iter == process_dumps.end()) { | 932 if (iter == process_dumps.end()) { |
974 std::unique_ptr<ProcessMemoryDump> new_pmd( | 933 std::unique_ptr<ProcessMemoryDump> new_pmd( |
975 new ProcessMemoryDump(session_state, dump_args)); | 934 new ProcessMemoryDump(session_state, dump_args)); |
976 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; | 935 iter = process_dumps.insert(std::make_pair(pid, std::move(new_pmd))).first; |
977 } | 936 } |
978 return iter->second.get(); | 937 return iter->second.get(); |
979 } | 938 } |
980 | 939 |
981 } // namespace trace_event | 940 } // namespace trace_event |
982 } // namespace base | 941 } // namespace base |
OLD | NEW |