| 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 |