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_stack_frame_deduplicator.h" | 5 #include "base/trace_event/heap_profiler_stack_frame_deduplicator.h" |
6 | 6 |
7 #include <iterator> | 7 #include <iterator> |
8 #include <memory> | 8 #include <memory> |
9 | 9 |
10 #include "base/macros.h" | 10 #include "base/macros.h" |
11 #include "base/trace_event/heap_profiler_allocation_context.h" | 11 #include "base/trace_event/heap_profiler_allocation_context.h" |
12 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
13 | 13 |
14 namespace base { | 14 namespace base { |
15 namespace trace_event { | 15 namespace trace_event { |
16 | 16 |
17 // Define all strings once, because the deduplicator requires pointer equality, | 17 // Define all strings once, because the deduplicator requires pointer equality, |
18 // and string interning is unreliable. | 18 // and string interning is unreliable. |
19 StackFrame kBrowserMain = StackFrame::FromTraceEventName("BrowserMain"); | 19 const char kBrowserMain[] = "BrowserMain"; |
20 StackFrame kRendererMain = StackFrame::FromTraceEventName("RendererMain"); | 20 const char kRendererMain[] = "RendererMain"; |
21 StackFrame kCreateWidget = StackFrame::FromTraceEventName("CreateWidget"); | 21 const char kCreateWidget[] = "CreateWidget"; |
22 StackFrame kInitialize = StackFrame::FromTraceEventName("Initialize"); | 22 const char kInitialize[] = "Initialize"; |
23 StackFrame kMalloc = StackFrame::FromTraceEventName("malloc"); | 23 const char kMalloc[] = "malloc"; |
24 | 24 |
25 TEST(StackFrameDeduplicatorTest, SingleBacktrace) { | 25 TEST(StackFrameDeduplicatorTest, SingleBacktrace) { |
26 StackFrame bt[] = {kBrowserMain, kCreateWidget, kMalloc}; | 26 StackFrame bt[] = {kBrowserMain, kCreateWidget, kMalloc}; |
27 | 27 |
28 // The call tree should look like this (index in brackets). | 28 // The call tree should look like this (index in brackets). |
29 // | 29 // |
30 // BrowserMain [0] | 30 // BrowserMain [0] |
31 // CreateWidget [1] | 31 // CreateWidget [1] |
32 // malloc [2] | 32 // malloc [2] |
33 | 33 |
34 std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator); | 34 std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator); |
35 ASSERT_EQ(2, dedup->Insert(std::begin(bt), std::end(bt))); | 35 ASSERT_EQ(2, dedup->Insert(std::begin(bt), std::end(bt))); |
36 | 36 |
37 auto iter = dedup->begin(); | 37 auto iter = dedup->begin(); |
38 ASSERT_EQ(kBrowserMain, (iter + 0)->frame); | 38 ASSERT_EQ(kBrowserMain, (iter + 0)->frame); |
39 ASSERT_EQ(-1, (iter + 0)->parent_frame_index); | 39 ASSERT_EQ(-1, (iter + 0)->parent_frame_index); |
40 | 40 |
41 ASSERT_EQ(kCreateWidget, (iter + 1)->frame); | 41 ASSERT_EQ(kCreateWidget, (iter + 1)->frame); |
42 ASSERT_EQ(0, (iter + 1)->parent_frame_index); | 42 ASSERT_EQ(0, (iter + 1)->parent_frame_index); |
43 | 43 |
44 ASSERT_EQ(kMalloc, (iter + 2)->frame); | 44 ASSERT_EQ(kMalloc, (iter + 2)->frame); |
45 ASSERT_EQ(1, (iter + 2)->parent_frame_index); | |
46 | |
47 ASSERT_EQ(iter + 3, dedup->end()); | |
48 } | |
49 | |
50 TEST(StackFrameDeduplicatorTest, SingleBacktraceWithNull) { | |
51 StackFrame null_frame = StackFrame::FromTraceEventName(nullptr); | |
52 StackFrame bt[] = {kBrowserMain, null_frame, kMalloc}; | |
53 | |
54 // Deduplicator doesn't care about what's inside StackFrames, | |
55 // and handles nullptr StackFrame values as any other. | |
56 // | |
57 // So the call tree should look like this (index in brackets). | |
58 // | |
59 // BrowserMain [0] | |
60 // (null) [1] | |
61 // malloc [2] | |
62 | |
63 std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator); | |
64 ASSERT_EQ(2, dedup->Insert(std::begin(bt), std::end(bt))); | |
65 | |
66 auto iter = dedup->begin(); | |
67 ASSERT_EQ(kBrowserMain, (iter + 0)->frame); | |
68 ASSERT_EQ(-1, (iter + 0)->parent_frame_index); | |
69 | |
70 ASSERT_EQ(null_frame, (iter + 1)->frame); | |
71 ASSERT_EQ(0, (iter + 1)->parent_frame_index); | |
72 | |
73 ASSERT_EQ(kMalloc, (iter + 2)->frame); | |
74 ASSERT_EQ(1, (iter + 2)->parent_frame_index); | 45 ASSERT_EQ(1, (iter + 2)->parent_frame_index); |
75 | 46 |
76 ASSERT_EQ(iter + 3, dedup->end()); | 47 ASSERT_EQ(iter + 3, dedup->end()); |
77 } | 48 } |
78 | 49 |
79 // Test that there can be different call trees (there can be multiple bottom | 50 // Test that there can be different call trees (there can be multiple bottom |
80 // frames). Also verify that frames with the same name but a different caller | 51 // frames). Also verify that frames with the same name but a different caller |
81 // are represented as distinct nodes. | 52 // are represented as distinct nodes. |
82 TEST(StackFrameDeduplicatorTest, MultipleRoots) { | 53 TEST(StackFrameDeduplicatorTest, MultipleRoots) { |
83 StackFrame bt0[] = {kBrowserMain, kCreateWidget}; | 54 StackFrame bt0[] = {kBrowserMain, kCreateWidget}; |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
141 | 112 |
142 ASSERT_EQ(iter + 3, dedup->end()); | 113 ASSERT_EQ(iter + 3, dedup->end()); |
143 | 114 |
144 // Inserting the same backtrace again should return the index of the existing | 115 // Inserting the same backtrace again should return the index of the existing |
145 // node. | 116 // node. |
146 ASSERT_EQ(1, dedup->Insert(std::begin(bt0), std::end(bt0))); | 117 ASSERT_EQ(1, dedup->Insert(std::begin(bt0), std::end(bt0))); |
147 ASSERT_EQ(2, dedup->Insert(std::begin(bt1), std::end(bt1))); | 118 ASSERT_EQ(2, dedup->Insert(std::begin(bt1), std::end(bt1))); |
148 ASSERT_EQ(dedup->begin() + 3, dedup->end()); | 119 ASSERT_EQ(dedup->begin() + 3, dedup->end()); |
149 } | 120 } |
150 | 121 |
| 122 TEST(StackFrameDeduplicatorTest, NullPaddingIsRemoved) { |
| 123 StackFrame bt0[] = {kBrowserMain, nullptr, nullptr, nullptr}; |
| 124 |
| 125 std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator); |
| 126 |
| 127 // There are four frames in the backtrace, but the null pointers should be |
| 128 // skipped, so only one frame is inserted, which will have index 0. |
| 129 ASSERT_EQ(4u, arraysize(bt0)); |
| 130 ASSERT_EQ(0, dedup->Insert(std::begin(bt0), std::end(bt0))); |
| 131 ASSERT_EQ(dedup->begin() + 1, dedup->end()); |
| 132 } |
| 133 |
151 } // namespace trace_event | 134 } // namespace trace_event |
152 } // namespace base | 135 } // namespace base |
OLD | NEW |