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/heap_profiler_heap_dump_writer.h" | 5 #include "base/trace_event/heap_profiler_heap_dump_writer.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/json/json_reader.h" | 13 #include "base/json/json_reader.h" |
14 #include "base/macros.h" | 14 #include "base/macros.h" |
15 #include "base/memory/ptr_util.h" | 15 #include "base/memory/ptr_util.h" |
16 #include "base/trace_event/heap_profiler_allocation_context.h" | 16 #include "base/trace_event/heap_profiler_allocation_context.h" |
17 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" | 17 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
18 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" | 18 #include "base/trace_event/heap_profiler_type_name_deduplicator.h" |
19 #include "base/trace_event/trace_event_argument.h" | 19 #include "base/trace_event/trace_event_argument.h" |
20 #include "base/values.h" | 20 #include "base/values.h" |
21 #include "testing/gtest/include/gtest/gtest.h" | 21 #include "testing/gtest/include/gtest/gtest.h" |
22 | 22 |
23 namespace { | 23 namespace { |
24 | 24 |
25 using base::trace_event::StackFrame; | |
26 | |
27 // Define all strings once, because the deduplicator requires pointer equality, | 25 // Define all strings once, because the deduplicator requires pointer equality, |
28 // and string interning is unreliable. | 26 // and string interning is unreliable. |
29 StackFrame kBrowserMain = StackFrame::FromTraceEventName("BrowserMain"); | 27 const char kBrowserMain[] = "BrowserMain"; |
30 StackFrame kRendererMain = StackFrame::FromTraceEventName("RendererMain"); | 28 const char kRendererMain[] = "RendererMain"; |
31 StackFrame kCreateWidget = StackFrame::FromTraceEventName("CreateWidget"); | 29 const char kCreateWidget[] = "CreateWidget"; |
32 StackFrame kInitialize = StackFrame::FromTraceEventName("Initialize"); | 30 const char kInitialize[] = "Initialize"; |
33 StackFrame kGetBitmap = StackFrame::FromTraceEventName("GetBitmap"); | 31 const char kGetBitmap[] = "GetBitmap"; |
34 | 32 |
35 const char kInt[] = "int"; | 33 const char kInt[] = "int"; |
36 const char kBool[] = "bool"; | 34 const char kBool[] = "bool"; |
37 const char kString[] = "string"; | 35 const char kString[] = "string"; |
38 | 36 |
39 } // namespace | 37 } // namespace |
40 | 38 |
41 namespace base { | 39 namespace base { |
42 namespace trace_event { | 40 namespace trace_event { |
43 namespace internal { | 41 namespace internal { |
(...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
173 ASSERT_EQ(large_value_str, size); | 171 ASSERT_EQ(large_value_str, size); |
174 | 172 |
175 std::string count; | 173 std::string count; |
176 ASSERT_TRUE(json_entry->GetString("count", &count)); | 174 ASSERT_TRUE(json_entry->GetString("count", &count)); |
177 ASSERT_EQ(large_value_str, count); | 175 ASSERT_EQ(large_value_str, count); |
178 } | 176 } |
179 | 177 |
180 TEST(HeapDumpWriterTest, BacktraceTypeNameTable) { | 178 TEST(HeapDumpWriterTest, BacktraceTypeNameTable) { |
181 hash_map<AllocationContext, AllocationMetrics> metrics_by_context; | 179 hash_map<AllocationContext, AllocationMetrics> metrics_by_context; |
182 | 180 |
183 AllocationContext ctx; | 181 AllocationContext ctx = AllocationContext::Empty(); |
184 ctx.backtrace.frames[0] = kBrowserMain; | 182 ctx.backtrace.frames[0] = kBrowserMain; |
185 ctx.backtrace.frames[1] = kCreateWidget; | 183 ctx.backtrace.frames[1] = kCreateWidget; |
186 ctx.backtrace.frame_count = 2; | |
187 ctx.type_name = kInt; | 184 ctx.type_name = kInt; |
188 | 185 |
189 // 10 bytes with context { type: int, bt: [BrowserMain, CreateWidget] }. | 186 // 10 bytes with context { type: int, bt: [BrowserMain, CreateWidget] }. |
190 metrics_by_context[ctx] = {10, 5}; | 187 metrics_by_context[ctx] = {10, 5}; |
191 | 188 |
192 ctx.type_name = kBool; | 189 ctx.type_name = kBool; |
193 | 190 |
194 // 18 bytes with context { type: bool, bt: [BrowserMain, CreateWidget] }. | 191 // 18 bytes with context { type: bool, bt: [BrowserMain, CreateWidget] }. |
195 metrics_by_context[ctx] = {18, 18}; | 192 metrics_by_context[ctx] = {18, 18}; |
196 | 193 |
197 ctx.backtrace.frames[0] = kRendererMain; | 194 ctx.backtrace.frames[0] = kRendererMain; |
198 ctx.backtrace.frames[1] = kInitialize; | 195 ctx.backtrace.frames[1] = kInitialize; |
199 ctx.backtrace.frame_count = 2; | |
200 | 196 |
201 // 30 bytes with context { type: bool, bt: [RendererMain, Initialize] }. | 197 // 30 bytes with context { type: bool, bt: [RendererMain, Initialize] }. |
202 metrics_by_context[ctx] = {30, 30}; | 198 metrics_by_context[ctx] = {30, 30}; |
203 | 199 |
204 ctx.type_name = kString; | 200 ctx.type_name = kString; |
205 | 201 |
206 // 19 bytes with context { type: string, bt: [RendererMain, Initialize] }. | 202 // 19 bytes with context { type: string, bt: [RendererMain, Initialize] }. |
207 metrics_by_context[ctx] = {19, 4}; | 203 metrics_by_context[ctx] = {19, 4}; |
208 | 204 |
209 // At this point the heap looks like this: | 205 // At this point the heap looks like this: |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 | 260 |
265 // The type breakdown of the entrie heap should have been dumped as well. | 261 // The type breakdown of the entrie heap should have been dumped as well. |
266 AssertSizeAndCountEq(dump, -1, type_id_int, {10, 5}); | 262 AssertSizeAndCountEq(dump, -1, type_id_int, {10, 5}); |
267 AssertSizeAndCountEq(dump, -1, type_id_bool, {48, 48}); | 263 AssertSizeAndCountEq(dump, -1, type_id_bool, {48, 48}); |
268 AssertSizeAndCountEq(dump, -1, type_id_string, {19, 4}); | 264 AssertSizeAndCountEq(dump, -1, type_id_string, {19, 4}); |
269 } | 265 } |
270 | 266 |
271 TEST(HeapDumpWriterTest, InsignificantValuesNotDumped) { | 267 TEST(HeapDumpWriterTest, InsignificantValuesNotDumped) { |
272 hash_map<AllocationContext, AllocationMetrics> metrics_by_context; | 268 hash_map<AllocationContext, AllocationMetrics> metrics_by_context; |
273 | 269 |
274 AllocationContext ctx; | 270 AllocationContext ctx = AllocationContext::Empty(); |
275 ctx.backtrace.frames[0] = kBrowserMain; | 271 ctx.backtrace.frames[0] = kBrowserMain; |
276 ctx.backtrace.frames[1] = kCreateWidget; | 272 ctx.backtrace.frames[1] = kCreateWidget; |
277 ctx.backtrace.frame_count = 2; | |
278 | 273 |
279 // 0.5 KiB and 1 chunk in BrowserMain -> CreateWidget itself. | 274 // 0.5 KiB and 1 chunk in BrowserMain -> CreateWidget itself. |
280 metrics_by_context[ctx] = {512, 1}; | 275 metrics_by_context[ctx] = {512, 1}; |
281 | 276 |
282 // 1 MiB and 1 chunk in BrowserMain -> CreateWidget -> GetBitmap. | 277 // 1 MiB and 1 chunk in BrowserMain -> CreateWidget -> GetBitmap. |
283 ctx.backtrace.frames[2] = kGetBitmap; | 278 ctx.backtrace.frames[2] = kGetBitmap; |
284 ctx.backtrace.frame_count = 3; | |
285 metrics_by_context[ctx] = {1024 * 1024, 1}; | 279 metrics_by_context[ctx] = {1024 * 1024, 1}; |
286 | 280 |
287 // 0.5 KiB and 1 chunk in BrowserMain -> CreateWidget -> Initialize. | 281 // 0.5 KiB and 1 chunk in BrowserMain -> CreateWidget -> Initialize. |
288 ctx.backtrace.frames[2] = kInitialize; | 282 ctx.backtrace.frames[2] = kInitialize; |
289 ctx.backtrace.frame_count = 3; | |
290 metrics_by_context[ctx] = {512, 1}; | 283 metrics_by_context[ctx] = {512, 1}; |
291 | 284 |
292 auto sf_deduplicator = WrapUnique(new StackFrameDeduplicator); | 285 auto sf_deduplicator = WrapUnique(new StackFrameDeduplicator); |
293 auto tn_deduplicator = WrapUnique(new TypeNameDeduplicator); | 286 auto tn_deduplicator = WrapUnique(new TypeNameDeduplicator); |
294 HeapDumpWriter writer(sf_deduplicator.get(), tn_deduplicator.get()); | 287 HeapDumpWriter writer(sf_deduplicator.get(), tn_deduplicator.get()); |
295 const std::set<Entry>& dump = writer.Summarize(metrics_by_context); | 288 const std::set<Entry>& dump = writer.Summarize(metrics_by_context); |
296 | 289 |
297 // Get the indices of the backtraces and types by adding them again to the | 290 // Get the indices of the backtraces and types by adding them again to the |
298 // deduplicator. Because they were added before, the same number is returned. | 291 // deduplicator. Because they were added before, the same number is returned. |
299 StackFrame bt0[] = {kBrowserMain, kCreateWidget, kGetBitmap}; | 292 StackFrame bt0[] = {kBrowserMain, kCreateWidget, kGetBitmap}; |
(...skipping 17 matching lines...) Expand all Loading... |
317 {1024 * 1024 + 512 + 512, 3}); | 310 {1024 * 1024 + 512 + 512, 3}); |
318 AssertSizeAndCountEq(dump, bt_browser_main, -1, {1024 * 1024 + 512 + 512, 3}); | 311 AssertSizeAndCountEq(dump, bt_browser_main, -1, {1024 * 1024 + 512 + 512, 3}); |
319 | 312 |
320 // Initialize was not significant, it should not have been dumped. | 313 // Initialize was not significant, it should not have been dumped. |
321 AssertNotDumped(dump, bt_initialize, -1); | 314 AssertNotDumped(dump, bt_initialize, -1); |
322 } | 315 } |
323 | 316 |
324 } // namespace internal | 317 } // namespace internal |
325 } // namespace trace_event | 318 } // namespace trace_event |
326 } // namespace base | 319 } // namespace base |
OLD | NEW |