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