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

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

Issue 1958703002: [tracing] Fix mising thread names in heap profiler (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Rename and annotate. Created 4 years, 7 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
« no previous file with comments | « base/trace_event/heap_profiler_allocation_context_tracker.cc ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 <stddef.h> 5 #include <stddef.h>
6 6
7 #include <iterator> 7 #include <iterator>
8 8
9 #include "base/memory/ref_counted.h" 9 #include "base/memory/ref_counted.h"
10 #include "base/pending_task.h" 10 #include "base/pending_task.h"
11 #include "base/trace_event/heap_profiler.h" 11 #include "base/trace_event/heap_profiler.h"
12 #include "base/trace_event/heap_profiler_allocation_context.h" 12 #include "base/trace_event/heap_profiler_allocation_context.h"
13 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" 13 #include "base/trace_event/heap_profiler_allocation_context_tracker.h"
14 #include "base/trace_event/trace_event.h" 14 #include "base/trace_event/trace_event.h"
15 #include "testing/gtest/include/gtest/gtest.h" 15 #include "testing/gtest/include/gtest/gtest.h"
16 16
17 namespace base { 17 namespace base {
18 namespace trace_event { 18 namespace trace_event {
19 19
20 // Define all strings once, because the pseudo stack requires pointer equality, 20 // Define all strings once, because the pseudo stack requires pointer equality,
21 // and string interning is unreliable. 21 // and string interning is unreliable.
22 const char kThreadName[] = "TestThread";
22 const char kCupcake[] = "Cupcake"; 23 const char kCupcake[] = "Cupcake";
23 const char kDonut[] = "Donut"; 24 const char kDonut[] = "Donut";
24 const char kEclair[] = "Eclair"; 25 const char kEclair[] = "Eclair";
25 const char kFroyo[] = "Froyo"; 26 const char kFroyo[] = "Froyo";
26 const char kGingerbread[] = "Gingerbread"; 27 const char kGingerbread[] = "Gingerbread";
27 28
28 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace 29 // Asserts that the fixed-size array |expected_backtrace| matches the backtrace
29 // in |AllocationContextTracker::GetContextSnapshot|. 30 // in |AllocationContextTracker::GetContextSnapshot|.
30 template <size_t N> 31 template <size_t N>
31 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) { 32 void AssertBacktraceEquals(const StackFrame(&expected_backtrace)[N]) {
(...skipping 10 matching lines...) Expand all
42 // string comparison. 43 // string comparison.
43 for (; actual != actual_bottom && expected != expected_bottom; 44 for (; actual != actual_bottom && expected != expected_bottom;
44 actual++, expected++) 45 actual++, expected++)
45 ASSERT_EQ(*expected, *actual); 46 ASSERT_EQ(*expected, *actual);
46 47
47 // Ensure that the height of the stacks is the same. 48 // Ensure that the height of the stacks is the same.
48 ASSERT_EQ(actual, actual_bottom); 49 ASSERT_EQ(actual, actual_bottom);
49 ASSERT_EQ(expected, expected_bottom); 50 ASSERT_EQ(expected, expected_bottom);
50 } 51 }
51 52
52 void AssertBacktraceEmpty() { 53 void AssertBacktraceContainsOnlyThreadName() {
54 StackFrame t = StackFrame::FromThreadName(kThreadName);
53 AllocationContext ctx = 55 AllocationContext ctx =
54 AllocationContextTracker::GetInstanceForCurrentThread() 56 AllocationContextTracker::GetInstanceForCurrentThread()
55 ->GetContextSnapshot(); 57 ->GetContextSnapshot();
56 58
57 ASSERT_EQ(0u, ctx.backtrace.frame_count); 59 ASSERT_EQ(1u, ctx.backtrace.frame_count);
60 ASSERT_EQ(t, ctx.backtrace.frames[0]);
58 } 61 }
59 62
60 class AllocationContextTrackerTest : public testing::Test { 63 class AllocationContextTrackerTest : public testing::Test {
61 public: 64 public:
62 void SetUp() override { 65 void SetUp() override {
63 TraceConfig config(""); 66 TraceConfig config("");
64 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE); 67 TraceLog::GetInstance()->SetEnabled(config, TraceLog::RECORDING_MODE);
65 AllocationContextTracker::SetCaptureMode( 68 AllocationContextTracker::SetCaptureMode(
66 AllocationContextTracker::CaptureMode::PSEUDO_STACK); 69 AllocationContextTracker::CaptureMode::PSEUDO_STACK);
70 AllocationContextTracker::SetCurrentThreadName(kThreadName);
67 } 71 }
68 72
69 void TearDown() override { 73 void TearDown() override {
70 AllocationContextTracker::SetCaptureMode( 74 AllocationContextTracker::SetCaptureMode(
71 AllocationContextTracker::CaptureMode::DISABLED); 75 AllocationContextTracker::CaptureMode::DISABLED);
72 TraceLog::GetInstance()->SetDisabled(); 76 TraceLog::GetInstance()->SetDisabled();
73 } 77 }
74 }; 78 };
75 79
76 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly. 80 // Check that |TRACE_EVENT| macros push and pop to the pseudo stack correctly.
77 TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) { 81 TEST_F(AllocationContextTrackerTest, PseudoStackScopedTrace) {
82 StackFrame t = StackFrame::FromThreadName(kThreadName);
78 StackFrame c = StackFrame::FromTraceEventName(kCupcake); 83 StackFrame c = StackFrame::FromTraceEventName(kCupcake);
79 StackFrame d = StackFrame::FromTraceEventName(kDonut); 84 StackFrame d = StackFrame::FromTraceEventName(kDonut);
80 StackFrame e = StackFrame::FromTraceEventName(kEclair); 85 StackFrame e = StackFrame::FromTraceEventName(kEclair);
81 StackFrame f = StackFrame::FromTraceEventName(kFroyo); 86 StackFrame f = StackFrame::FromTraceEventName(kFroyo);
82 87
83 AssertBacktraceEmpty(); 88 AssertBacktraceContainsOnlyThreadName();
84 89
85 { 90 {
86 TRACE_EVENT0("Testing", kCupcake); 91 TRACE_EVENT0("Testing", kCupcake);
87 StackFrame frame_c[] = {c}; 92 StackFrame frame_c[] = {t, c};
88 AssertBacktraceEquals(frame_c); 93 AssertBacktraceEquals(frame_c);
89 94
90 { 95 {
91 TRACE_EVENT0("Testing", kDonut); 96 TRACE_EVENT0("Testing", kDonut);
92 StackFrame frame_cd[] = {c, d}; 97 StackFrame frame_cd[] = {t, c, d};
93 AssertBacktraceEquals(frame_cd); 98 AssertBacktraceEquals(frame_cd);
94 } 99 }
95 100
96 AssertBacktraceEquals(frame_c); 101 AssertBacktraceEquals(frame_c);
97 102
98 { 103 {
99 TRACE_EVENT0("Testing", kEclair); 104 TRACE_EVENT0("Testing", kEclair);
100 StackFrame frame_ce[] = {c, e}; 105 StackFrame frame_ce[] = {t, c, e};
101 AssertBacktraceEquals(frame_ce); 106 AssertBacktraceEquals(frame_ce);
102 } 107 }
103 108
104 AssertBacktraceEquals(frame_c); 109 AssertBacktraceEquals(frame_c);
105 } 110 }
106 111
107 AssertBacktraceEmpty(); 112 AssertBacktraceContainsOnlyThreadName();
108 113
109 { 114 {
110 TRACE_EVENT0("Testing", kFroyo); 115 TRACE_EVENT0("Testing", kFroyo);
111 StackFrame frame_f[] = {f}; 116 StackFrame frame_f[] = {t, f};
112 AssertBacktraceEquals(frame_f); 117 AssertBacktraceEquals(frame_f);
113 } 118 }
114 119
115 AssertBacktraceEmpty(); 120 AssertBacktraceContainsOnlyThreadName();
116 } 121 }
117 122
118 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and 123 // Same as |PseudoStackScopedTrace|, but now test the |TRACE_EVENT_BEGIN| and
119 // |TRACE_EVENT_END| macros. 124 // |TRACE_EVENT_END| macros.
120 TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) { 125 TEST_F(AllocationContextTrackerTest, PseudoStackBeginEndTrace) {
126 StackFrame t = StackFrame::FromThreadName(kThreadName);
121 StackFrame c = StackFrame::FromTraceEventName(kCupcake); 127 StackFrame c = StackFrame::FromTraceEventName(kCupcake);
122 StackFrame d = StackFrame::FromTraceEventName(kDonut); 128 StackFrame d = StackFrame::FromTraceEventName(kDonut);
123 StackFrame e = StackFrame::FromTraceEventName(kEclair); 129 StackFrame e = StackFrame::FromTraceEventName(kEclair);
124 StackFrame f = StackFrame::FromTraceEventName(kFroyo); 130 StackFrame f = StackFrame::FromTraceEventName(kFroyo);
125 131
126 StackFrame frame_c[] = {c}; 132 StackFrame frame_c[] = {t, c};
127 StackFrame frame_cd[] = {c, d}; 133 StackFrame frame_cd[] = {t, c, d};
128 StackFrame frame_ce[] = {c, e}; 134 StackFrame frame_ce[] = {t, c, e};
129 StackFrame frame_f[] = {f}; 135 StackFrame frame_f[] = {t, f};
130 136
131 AssertBacktraceEmpty(); 137 AssertBacktraceContainsOnlyThreadName();
132 138
133 TRACE_EVENT_BEGIN0("Testing", kCupcake); 139 TRACE_EVENT_BEGIN0("Testing", kCupcake);
134 AssertBacktraceEquals(frame_c); 140 AssertBacktraceEquals(frame_c);
135 141
136 TRACE_EVENT_BEGIN0("Testing", kDonut); 142 TRACE_EVENT_BEGIN0("Testing", kDonut);
137 AssertBacktraceEquals(frame_cd); 143 AssertBacktraceEquals(frame_cd);
138 TRACE_EVENT_END0("Testing", kDonut); 144 TRACE_EVENT_END0("Testing", kDonut);
139 145
140 AssertBacktraceEquals(frame_c); 146 AssertBacktraceEquals(frame_c);
141 147
142 TRACE_EVENT_BEGIN0("Testing", kEclair); 148 TRACE_EVENT_BEGIN0("Testing", kEclair);
143 AssertBacktraceEquals(frame_ce); 149 AssertBacktraceEquals(frame_ce);
144 TRACE_EVENT_END0("Testing", kEclair); 150 TRACE_EVENT_END0("Testing", kEclair);
145 151
146 AssertBacktraceEquals(frame_c); 152 AssertBacktraceEquals(frame_c);
147 TRACE_EVENT_END0("Testing", kCupcake); 153 TRACE_EVENT_END0("Testing", kCupcake);
148 154
149 AssertBacktraceEmpty(); 155 AssertBacktraceContainsOnlyThreadName();
150 156
151 TRACE_EVENT_BEGIN0("Testing", kFroyo); 157 TRACE_EVENT_BEGIN0("Testing", kFroyo);
152 AssertBacktraceEquals(frame_f); 158 AssertBacktraceEquals(frame_f);
153 TRACE_EVENT_END0("Testing", kFroyo); 159 TRACE_EVENT_END0("Testing", kFroyo);
154 160
155 AssertBacktraceEmpty(); 161 AssertBacktraceContainsOnlyThreadName();
156 } 162 }
157 163
158 TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) { 164 TEST_F(AllocationContextTrackerTest, PseudoStackMixedTrace) {
165 StackFrame t = StackFrame::FromThreadName(kThreadName);
159 StackFrame c = StackFrame::FromTraceEventName(kCupcake); 166 StackFrame c = StackFrame::FromTraceEventName(kCupcake);
160 StackFrame d = StackFrame::FromTraceEventName(kDonut); 167 StackFrame d = StackFrame::FromTraceEventName(kDonut);
161 StackFrame e = StackFrame::FromTraceEventName(kEclair); 168 StackFrame e = StackFrame::FromTraceEventName(kEclair);
162 StackFrame f = StackFrame::FromTraceEventName(kFroyo); 169 StackFrame f = StackFrame::FromTraceEventName(kFroyo);
163 170
164 StackFrame frame_c[] = {c}; 171 StackFrame frame_c[] = {t, c};
165 StackFrame frame_cd[] = {c, d}; 172 StackFrame frame_cd[] = {t, c, d};
166 StackFrame frame_e[] = {e}; 173 StackFrame frame_e[] = {t, e};
167 StackFrame frame_ef[] = {e, f}; 174 StackFrame frame_ef[] = {t, e, f};
168 175
169 AssertBacktraceEmpty(); 176 AssertBacktraceContainsOnlyThreadName();
170 177
171 TRACE_EVENT_BEGIN0("Testing", kCupcake); 178 TRACE_EVENT_BEGIN0("Testing", kCupcake);
172 AssertBacktraceEquals(frame_c); 179 AssertBacktraceEquals(frame_c);
173 180
174 { 181 {
175 TRACE_EVENT0("Testing", kDonut); 182 TRACE_EVENT0("Testing", kDonut);
176 AssertBacktraceEquals(frame_cd); 183 AssertBacktraceEquals(frame_cd);
177 } 184 }
178 185
179 AssertBacktraceEquals(frame_c); 186 AssertBacktraceEquals(frame_c);
180 TRACE_EVENT_END0("Testing", kCupcake); 187 TRACE_EVENT_END0("Testing", kCupcake);
181 AssertBacktraceEmpty(); 188 AssertBacktraceContainsOnlyThreadName();
182 189
183 { 190 {
184 TRACE_EVENT0("Testing", kEclair); 191 TRACE_EVENT0("Testing", kEclair);
185 AssertBacktraceEquals(frame_e); 192 AssertBacktraceEquals(frame_e);
186 193
187 TRACE_EVENT_BEGIN0("Testing", kFroyo); 194 TRACE_EVENT_BEGIN0("Testing", kFroyo);
188 AssertBacktraceEquals(frame_ef); 195 AssertBacktraceEquals(frame_ef);
189 TRACE_EVENT_END0("Testing", kFroyo); 196 TRACE_EVENT_END0("Testing", kFroyo);
190 AssertBacktraceEquals(frame_e); 197 AssertBacktraceEquals(frame_e);
191 } 198 }
192 199
193 AssertBacktraceEmpty(); 200 AssertBacktraceContainsOnlyThreadName();
194 } 201 }
195 202
196 TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) { 203 TEST_F(AllocationContextTrackerTest, BacktraceTakesTop) {
204 StackFrame t = StackFrame::FromThreadName(kThreadName);
197 StackFrame c = StackFrame::FromTraceEventName(kCupcake); 205 StackFrame c = StackFrame::FromTraceEventName(kCupcake);
198 StackFrame f = StackFrame::FromTraceEventName(kFroyo); 206 StackFrame f = StackFrame::FromTraceEventName(kFroyo);
199 207
200 // Push 12 events onto the pseudo stack. 208 // Push 11 events onto the pseudo stack.
201 TRACE_EVENT0("Testing", kCupcake); 209 TRACE_EVENT0("Testing", kCupcake);
202 TRACE_EVENT0("Testing", kCupcake); 210 TRACE_EVENT0("Testing", kCupcake);
203 TRACE_EVENT0("Testing", kCupcake); 211 TRACE_EVENT0("Testing", kCupcake);
204 TRACE_EVENT0("Testing", kCupcake);
205 212
206 TRACE_EVENT0("Testing", kCupcake); 213 TRACE_EVENT0("Testing", kCupcake);
207 TRACE_EVENT0("Testing", kCupcake); 214 TRACE_EVENT0("Testing", kCupcake);
208 TRACE_EVENT0("Testing", kCupcake); 215 TRACE_EVENT0("Testing", kCupcake);
209 TRACE_EVENT0("Testing", kCupcake); 216 TRACE_EVENT0("Testing", kCupcake);
210 217
211 TRACE_EVENT0("Testing", kCupcake); 218 TRACE_EVENT0("Testing", kCupcake);
212 TRACE_EVENT0("Testing", kDonut); 219 TRACE_EVENT0("Testing", kDonut);
213 TRACE_EVENT0("Testing", kEclair); 220 TRACE_EVENT0("Testing", kEclair);
214 TRACE_EVENT0("Testing", kFroyo); 221 TRACE_EVENT0("Testing", kFroyo);
215 222
216 { 223 {
217 TRACE_EVENT0("Testing", kGingerbread); 224 TRACE_EVENT0("Testing", kGingerbread);
218 AllocationContext ctx = 225 AllocationContext ctx =
219 AllocationContextTracker::GetInstanceForCurrentThread() 226 AllocationContextTracker::GetInstanceForCurrentThread()
220 ->GetContextSnapshot(); 227 ->GetContextSnapshot();
221 228
222 // The pseudo stack relies on pointer equality, not deep string comparisons. 229 // The pseudo stack relies on pointer equality, not deep string comparisons.
223 ASSERT_EQ(c, ctx.backtrace.frames[0]); 230 ASSERT_EQ(t, ctx.backtrace.frames[0]);
231 ASSERT_EQ(c, ctx.backtrace.frames[1]);
224 ASSERT_EQ(f, ctx.backtrace.frames[11]); 232 ASSERT_EQ(f, ctx.backtrace.frames[11]);
225 } 233 }
226 234
227 { 235 {
228 AllocationContext ctx = 236 AllocationContext ctx =
229 AllocationContextTracker::GetInstanceForCurrentThread() 237 AllocationContextTracker::GetInstanceForCurrentThread()
230 ->GetContextSnapshot(); 238 ->GetContextSnapshot();
231 ASSERT_EQ(c, ctx.backtrace.frames[0]); 239 ASSERT_EQ(t, ctx.backtrace.frames[0]);
240 ASSERT_EQ(c, ctx.backtrace.frames[1]);
232 ASSERT_EQ(f, ctx.backtrace.frames[11]); 241 ASSERT_EQ(f, ctx.backtrace.frames[11]);
233 } 242 }
234 } 243 }
235 244
236 TEST_F(AllocationContextTrackerTest, SetCurrentThreadName) {
237 TRACE_EVENT0("Testing", kCupcake);
238
239 // Test if the thread name is inserted into backtrace.
240 const char kThread1[] = "thread1";
241 AllocationContextTracker::SetCurrentThreadName(kThread1);
242 AllocationContext ctx1 =
243 AllocationContextTracker::GetInstanceForCurrentThread()
244 ->GetContextSnapshot();
245 ASSERT_EQ(StackFrame::FromThreadName(kThread1), ctx1.backtrace.frames[0]);
246 ASSERT_EQ(StackFrame::FromTraceEventName(kCupcake), ctx1.backtrace.frames[1]);
247
248 // Test if the thread name is reset.
249 const char kThread2[] = "thread2";
250 AllocationContextTracker::SetCurrentThreadName(kThread2);
251 AllocationContext ctx2 =
252 AllocationContextTracker::GetInstanceForCurrentThread()
253 ->GetContextSnapshot();
254 ASSERT_EQ(StackFrame::FromThreadName(kThread2), ctx2.backtrace.frames[0]);
255 ASSERT_EQ(StackFrame::FromTraceEventName(kCupcake), ctx2.backtrace.frames[1]);
256 }
257
258 TEST_F(AllocationContextTrackerTest, TrackTaskContext) { 245 TEST_F(AllocationContextTrackerTest, TrackTaskContext) {
259 const char kContext1[] = "context1"; 246 const char kContext1[] = "context1";
260 const char kContext2[] = "context2"; 247 const char kContext2[] = "context2";
261 { 248 {
262 // The context from the scoped task event should be used as type name. 249 // The context from the scoped task event should be used as type name.
263 TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event1(kContext1); 250 TRACE_HEAP_PROFILER_API_SCOPED_TASK_EXECUTION event1(kContext1);
264 AllocationContext ctx1 = 251 AllocationContext ctx1 =
265 AllocationContextTracker::GetInstanceForCurrentThread() 252 AllocationContextTracker::GetInstanceForCurrentThread()
266 ->GetContextSnapshot(); 253 ->GetContextSnapshot();
267 ASSERT_EQ(kContext1, ctx1.type_name); 254 ASSERT_EQ(kContext1, ctx1.type_name);
(...skipping 21 matching lines...) Expand all
289 AllocationContextTracker::GetInstanceForCurrentThread() 276 AllocationContextTracker::GetInstanceForCurrentThread()
290 ->GetContextSnapshot(); 277 ->GetContextSnapshot();
291 const StringPiece kTracingOverhead("tracing_overhead"); 278 const StringPiece kTracingOverhead("tracing_overhead");
292 ASSERT_EQ(kTracingOverhead, 279 ASSERT_EQ(kTracingOverhead,
293 static_cast<const char*>(ctx.backtrace.frames[0].value)); 280 static_cast<const char*>(ctx.backtrace.frames[0].value));
294 ASSERT_EQ(1u, ctx.backtrace.frame_count); 281 ASSERT_EQ(1u, ctx.backtrace.frame_count);
295 } 282 }
296 283
297 } // namespace trace_event 284 } // namespace trace_event
298 } // namespace base 285 } // namespace base
OLDNEW
« no previous file with comments | « base/trace_event/heap_profiler_allocation_context_tracker.cc ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698