Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(46)

Side by Side Diff: base/trace_event/heap_profiler_allocation_context_tracker.cc

Issue 1839503002: [tracing] Add native allocation tracing mode. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Address comments Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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/heap_profiler_allocation_context_tracker.h" 5 #include "base/trace_event/heap_profiler_allocation_context_tracker.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <iterator> 8 #include <iterator>
9 9
10 #include "base/allocator/features.h"
10 #include "base/atomicops.h" 11 #include "base/atomicops.h"
11 #include "base/threading/thread_local_storage.h" 12 #include "base/threading/thread_local_storage.h"
12 #include "base/trace_event/heap_profiler_allocation_context.h" 13 #include "base/trace_event/heap_profiler_allocation_context.h"
13 14
14 namespace base { 15 namespace base {
15 namespace trace_event { 16 namespace trace_event {
16 17
17 subtle::Atomic32 AllocationContextTracker::capture_enabled_ = 0; 18 subtle::Atomic32 AllocationContextTracker::capture_mode_ =
19 static_cast<int32_t>(AllocationContextTracker::CaptureMode::DISABLED);
18 20
19 namespace { 21 namespace {
20 22
21 const size_t kMaxStackDepth = 128u; 23 const size_t kMaxStackDepth = 128u;
22 const size_t kMaxTaskDepth = 16u; 24 const size_t kMaxTaskDepth = 16u;
23 AllocationContextTracker* const kInitializingSentinel = 25 AllocationContextTracker* const kInitializingSentinel =
24 reinterpret_cast<AllocationContextTracker*>(-1); 26 reinterpret_cast<AllocationContextTracker*>(-1);
25 27
26 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER; 28 ThreadLocalStorage::StaticSlot g_tls_alloc_ctx_tracker = TLS_INITIALIZER;
27 29
(...skipping 23 matching lines...) Expand all
51 } 53 }
52 54
53 AllocationContextTracker::AllocationContextTracker() : thread_name_(nullptr) { 55 AllocationContextTracker::AllocationContextTracker() : thread_name_(nullptr) {
54 pseudo_stack_.reserve(kMaxStackDepth); 56 pseudo_stack_.reserve(kMaxStackDepth);
55 task_contexts_.reserve(kMaxTaskDepth); 57 task_contexts_.reserve(kMaxTaskDepth);
56 } 58 }
57 AllocationContextTracker::~AllocationContextTracker() {} 59 AllocationContextTracker::~AllocationContextTracker() {}
58 60
59 // static 61 // static
60 void AllocationContextTracker::SetCurrentThreadName(const char* name) { 62 void AllocationContextTracker::SetCurrentThreadName(const char* name) {
61 if (name && capture_enabled()) { 63 if (name && capture_mode() != CaptureMode::DISABLED) {
62 GetInstanceForCurrentThread()->thread_name_ = name; 64 GetInstanceForCurrentThread()->thread_name_ = name;
63 } 65 }
64 } 66 }
65 67
66 // static 68 // static
67 void AllocationContextTracker::SetCaptureEnabled(bool enabled) { 69 void AllocationContextTracker::SetCaptureMode(CaptureMode mode) {
68 // When enabling capturing, also initialize the TLS slot. This does not create 70 // When enabling capturing, also initialize the TLS slot. This does not create
69 // a TLS instance yet. 71 // a TLS instance yet.
70 if (enabled && !g_tls_alloc_ctx_tracker.initialized()) 72 if (mode != CaptureMode::DISABLED && !g_tls_alloc_ctx_tracker.initialized())
71 g_tls_alloc_ctx_tracker.Initialize(DestructAllocationContextTracker); 73 g_tls_alloc_ctx_tracker.Initialize(DestructAllocationContextTracker);
72 74
73 // Release ordering ensures that when a thread observes |capture_enabled_| to 75 // Release ordering ensures that when a thread observes |capture_mode_| to
74 // be true through an acquire load, the TLS slot has been initialized. 76 // be true through an acquire load, the TLS slot has been initialized.
75 subtle::Release_Store(&capture_enabled_, enabled); 77 subtle::Release_Store(&capture_mode_, static_cast<int32_t>(mode));
76 } 78 }
77 79
78 void AllocationContextTracker::PushPseudoStackFrame( 80 void AllocationContextTracker::PushPseudoStackFrame(
79 const char* trace_event_name) { 81 const char* trace_event_name) {
80 // Impose a limit on the height to verify that every push is popped, because 82 // Impose a limit on the height to verify that every push is popped, because
81 // in practice the pseudo stack never grows higher than ~20 frames. 83 // in practice the pseudo stack never grows higher than ~20 frames.
82 if (pseudo_stack_.size() < kMaxStackDepth) 84 if (pseudo_stack_.size() < kMaxStackDepth)
83 pseudo_stack_.push_back(trace_event_name); 85 pseudo_stack_.push_back(trace_event_name);
84 else 86 else
85 NOTREACHED(); 87 NOTREACHED();
(...skipping 23 matching lines...) Expand all
109 else 111 else
110 NOTREACHED(); 112 NOTREACHED();
111 } 113 }
112 114
113 void AllocationContextTracker::PopCurrentTaskContext(const char* context) { 115 void AllocationContextTracker::PopCurrentTaskContext(const char* context) {
114 DCHECK_EQ(context, task_contexts_.back()) 116 DCHECK_EQ(context, task_contexts_.back())
115 << "Encountered an unmatched context end"; 117 << "Encountered an unmatched context end";
116 task_contexts_.pop_back(); 118 task_contexts_.pop_back();
117 } 119 }
118 120
119 // static
120 AllocationContext AllocationContextTracker::GetContextSnapshot() { 121 AllocationContext AllocationContextTracker::GetContextSnapshot() {
121 AllocationContext ctx; 122 AllocationContext ctx;
122 123
123 // Fill the backtrace. 124 CaptureMode mode = static_cast<CaptureMode>(
124 { 125 subtle::NoBarrier_Load(&capture_mode_));
125 auto backtrace = std::begin(ctx.backtrace.frames);
126 auto backtrace_end = std::end(ctx.backtrace.frames);
127 126
128 // Add the thread name as the first entry 127 auto backtrace = std::begin(ctx.backtrace.frames);
129 if (thread_name_) { 128 auto backtrace_end = std::end(ctx.backtrace.frames);
130 *backtrace++ = StackFrame::FromThreadName(thread_name_);
131 }
132 129
133 for (const auto& event_name: pseudo_stack_) { 130 // Add the thread name as the first entry
134 if (backtrace == backtrace_end) { 131 if (thread_name_) {
132 *backtrace++ = StackFrame::FromThreadName(thread_name_);
133 }
134
135 switch (mode) {
136 case CaptureMode::DISABLED:
137 {
135 break; 138 break;
136 } 139 }
137 *backtrace++ = StackFrame::FromTraceEventName(event_name); 140 case CaptureMode::PSEUDO_STACK:
138 } 141 {
142 for (const auto& event_name: pseudo_stack_) {
143 if (backtrace == backtrace_end) {
144 break;
145 }
146 *backtrace++ = StackFrame::FromTraceEventName(event_name);
147 }
148 break;
149 }
150 #if ENABLE_NATIVE_ALLOCATION_TRACES
151 case CaptureMode::NATIVE_STACK:
152 {
153 // base::trace_event::AllocationContextTracker::GetContextSnapshot()
154 const size_t kKnownFrameCount = 1;
139 155
140 ctx.backtrace.frame_count = backtrace - std::begin(ctx.backtrace.frames); 156 const void* frames[Backtrace::kMaxFrameCount];
157 size_t frame_count = debug::TraceStackFramePointers(
158 frames,
159 backtrace_end - backtrace,
Primiano Tucci (use gerrit) 2016/04/21 20:08:21 this will still return only the stack frames close
Dmitry Skiba 2016/04/22 06:31:15 No, you are right, I'm returning N bottom frames,
Primiano Tucci (use gerrit) 2016/04/22 09:02:46 I understand this but I believe that all the clust
160 kKnownFrameCount);
Primiano Tucci (use gerrit) 2016/04/21 20:08:21 you can just s|kKnownFrameCount|1 /* skip_initial
161
162 // Copy frames backwards
163 for (ssize_t i = frame_count - 1; i >= 0; --i) {
164 const void* frame = frames[i];
165 *backtrace++ = StackFrame::FromProgramCounter(frame);
166 }
167 break;
168 }
169 #endif // ENABLE_NATIVE_ALLOCATION_TRACES
141 } 170 }
142 171
172 ctx.backtrace.frame_count = backtrace - std::begin(ctx.backtrace.frames);
173
143 // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension 174 // TODO(ssid): Fix crbug.com/594803 to add file name as 3rd dimension
144 // (component name) in the heap profiler and not piggy back on the type name. 175 // (component name) in the heap profiler and not piggy back on the type name.
145 ctx.type_name = task_contexts_.empty() ? nullptr : task_contexts_.back(); 176 ctx.type_name = task_contexts_.empty() ? nullptr : task_contexts_.back();
146 177
147 return ctx; 178 return ctx;
148 } 179 }
149 180
150 } // namespace trace_event 181 } // namespace trace_event
151 } // namespace base 182 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698