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/process_memory_dump.h" | 5 #include "base/trace_event/process_memory_dump.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 | 8 |
9 #include "base/memory/aligned_memory.h" | 9 #include "base/memory/aligned_memory.h" |
10 #include "base/process/process_metrics.h" | 10 #include "base/process/process_metrics.h" |
11 #include "base/trace_event/memory_allocator_dump_guid.h" | 11 #include "base/trace_event/memory_allocator_dump_guid.h" |
12 #include "base/trace_event/trace_event_argument.h" | 12 #include "base/trace_event/trace_event_argument.h" |
13 #include "testing/gtest/include/gtest/gtest.h" | 13 #include "testing/gtest/include/gtest/gtest.h" |
14 | 14 |
15 namespace base { | 15 namespace base { |
16 namespace trace_event { | 16 namespace trace_event { |
17 | 17 |
18 namespace { | 18 namespace { |
19 TracedValue* GetHeapDump(const ProcessMemoryDump& pmd, const char* name) { | 19 TracedValue* GetHeapDump(const ProcessMemoryDump& pmd, const char* name) { |
20 auto it = pmd.heap_dumps().find(name); | 20 auto it = pmd.heap_dumps().find(name); |
21 return it == pmd.heap_dumps().end() ? nullptr : it->second.get(); | 21 return it == pmd.heap_dumps().end() ? nullptr : it->second.get(); |
22 } | 22 } |
23 } // namespace | 23 } // namespace |
24 | 24 |
25 TEST(ProcessMemoryDumpTest, Clear) { | 25 TEST(ProcessMemoryDumpTest, Clear) { |
26 scoped_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(nullptr)); | 26 std::unique_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(nullptr)); |
27 pmd1->CreateAllocatorDump("mad1"); | 27 pmd1->CreateAllocatorDump("mad1"); |
28 pmd1->CreateAllocatorDump("mad2"); | 28 pmd1->CreateAllocatorDump("mad2"); |
29 ASSERT_FALSE(pmd1->allocator_dumps().empty()); | 29 ASSERT_FALSE(pmd1->allocator_dumps().empty()); |
30 | 30 |
31 pmd1->process_totals()->set_resident_set_bytes(42); | 31 pmd1->process_totals()->set_resident_set_bytes(42); |
32 pmd1->set_has_process_totals(); | 32 pmd1->set_has_process_totals(); |
33 | 33 |
34 pmd1->process_mmaps()->AddVMRegion(ProcessMemoryMaps::VMRegion()); | 34 pmd1->process_mmaps()->AddVMRegion(ProcessMemoryMaps::VMRegion()); |
35 pmd1->set_has_process_mmaps(); | 35 pmd1->set_has_process_mmaps(); |
36 | 36 |
(...skipping 10 matching lines...) Expand all Loading... |
47 ASSERT_TRUE(pmd1->allocator_dumps_edges().empty()); | 47 ASSERT_TRUE(pmd1->allocator_dumps_edges().empty()); |
48 ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad1")); | 48 ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad1")); |
49 ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2")); | 49 ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2")); |
50 ASSERT_FALSE(pmd1->has_process_totals()); | 50 ASSERT_FALSE(pmd1->has_process_totals()); |
51 ASSERT_FALSE(pmd1->has_process_mmaps()); | 51 ASSERT_FALSE(pmd1->has_process_mmaps()); |
52 ASSERT_TRUE(pmd1->process_mmaps()->vm_regions().empty()); | 52 ASSERT_TRUE(pmd1->process_mmaps()->vm_regions().empty()); |
53 ASSERT_EQ(nullptr, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1)); | 53 ASSERT_EQ(nullptr, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1)); |
54 ASSERT_EQ(nullptr, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2)); | 54 ASSERT_EQ(nullptr, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2)); |
55 | 55 |
56 // Check that calling AsValueInto() doesn't cause a crash. | 56 // Check that calling AsValueInto() doesn't cause a crash. |
57 scoped_ptr<TracedValue> traced_value(new TracedValue); | 57 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
58 pmd1->AsValueInto(traced_value.get()); | 58 pmd1->AsValueInto(traced_value.get()); |
59 | 59 |
60 // Check that the pmd can be reused and behaves as expected. | 60 // Check that the pmd can be reused and behaves as expected. |
61 auto mad1 = pmd1->CreateAllocatorDump("mad1"); | 61 auto mad1 = pmd1->CreateAllocatorDump("mad1"); |
62 auto mad3 = pmd1->CreateAllocatorDump("mad3"); | 62 auto mad3 = pmd1->CreateAllocatorDump("mad3"); |
63 auto shared_mad1 = pmd1->CreateSharedGlobalAllocatorDump(shared_mad_guid1); | 63 auto shared_mad1 = pmd1->CreateSharedGlobalAllocatorDump(shared_mad_guid1); |
64 auto shared_mad2 = | 64 auto shared_mad2 = |
65 pmd1->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid2); | 65 pmd1->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid2); |
66 ASSERT_EQ(4u, pmd1->allocator_dumps().size()); | 66 ASSERT_EQ(4u, pmd1->allocator_dumps().size()); |
67 ASSERT_EQ(mad1, pmd1->GetAllocatorDump("mad1")); | 67 ASSERT_EQ(mad1, pmd1->GetAllocatorDump("mad1")); |
68 ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2")); | 68 ASSERT_EQ(nullptr, pmd1->GetAllocatorDump("mad2")); |
69 ASSERT_EQ(mad3, pmd1->GetAllocatorDump("mad3")); | 69 ASSERT_EQ(mad3, pmd1->GetAllocatorDump("mad3")); |
70 ASSERT_EQ(shared_mad1, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1)); | 70 ASSERT_EQ(shared_mad1, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid1)); |
71 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); | 71 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); |
72 ASSERT_EQ(shared_mad2, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2)); | 72 ASSERT_EQ(shared_mad2, pmd1->GetSharedGlobalAllocatorDump(shared_mad_guid2)); |
73 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad2->flags()); | 73 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad2->flags()); |
74 | 74 |
75 traced_value.reset(new TracedValue); | 75 traced_value.reset(new TracedValue); |
76 pmd1->AsValueInto(traced_value.get()); | 76 pmd1->AsValueInto(traced_value.get()); |
77 | 77 |
78 pmd1.reset(); | 78 pmd1.reset(); |
79 } | 79 } |
80 | 80 |
81 TEST(ProcessMemoryDumpTest, TakeAllDumpsFrom) { | 81 TEST(ProcessMemoryDumpTest, TakeAllDumpsFrom) { |
82 scoped_ptr<TracedValue> traced_value(new TracedValue); | 82 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
83 TracedValue* heap_dumps_ptr[4]; | 83 TracedValue* heap_dumps_ptr[4]; |
84 scoped_ptr<TracedValue> heap_dump; | 84 std::unique_ptr<TracedValue> heap_dump; |
85 | 85 |
86 scoped_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(nullptr)); | 86 std::unique_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(nullptr)); |
87 auto mad1_1 = pmd1->CreateAllocatorDump("pmd1/mad1"); | 87 auto mad1_1 = pmd1->CreateAllocatorDump("pmd1/mad1"); |
88 auto mad1_2 = pmd1->CreateAllocatorDump("pmd1/mad2"); | 88 auto mad1_2 = pmd1->CreateAllocatorDump("pmd1/mad2"); |
89 pmd1->AddOwnershipEdge(mad1_1->guid(), mad1_2->guid()); | 89 pmd1->AddOwnershipEdge(mad1_1->guid(), mad1_2->guid()); |
90 heap_dump.reset(new TracedValue); | 90 heap_dump.reset(new TracedValue); |
91 heap_dumps_ptr[0] = heap_dump.get(); | 91 heap_dumps_ptr[0] = heap_dump.get(); |
92 pmd1->AddHeapDump("pmd1/heap_dump1", std::move(heap_dump)); | 92 pmd1->AddHeapDump("pmd1/heap_dump1", std::move(heap_dump)); |
93 heap_dump.reset(new TracedValue); | 93 heap_dump.reset(new TracedValue); |
94 heap_dumps_ptr[1] = heap_dump.get(); | 94 heap_dumps_ptr[1] = heap_dump.get(); |
95 pmd1->AddHeapDump("pmd1/heap_dump2", std::move(heap_dump)); | 95 pmd1->AddHeapDump("pmd1/heap_dump2", std::move(heap_dump)); |
96 | 96 |
97 scoped_ptr<ProcessMemoryDump> pmd2(new ProcessMemoryDump(nullptr)); | 97 std::unique_ptr<ProcessMemoryDump> pmd2(new ProcessMemoryDump(nullptr)); |
98 auto mad2_1 = pmd2->CreateAllocatorDump("pmd2/mad1"); | 98 auto mad2_1 = pmd2->CreateAllocatorDump("pmd2/mad1"); |
99 auto mad2_2 = pmd2->CreateAllocatorDump("pmd2/mad2"); | 99 auto mad2_2 = pmd2->CreateAllocatorDump("pmd2/mad2"); |
100 pmd2->AddOwnershipEdge(mad2_1->guid(), mad2_2->guid()); | 100 pmd2->AddOwnershipEdge(mad2_1->guid(), mad2_2->guid()); |
101 heap_dump.reset(new TracedValue); | 101 heap_dump.reset(new TracedValue); |
102 heap_dumps_ptr[2] = heap_dump.get(); | 102 heap_dumps_ptr[2] = heap_dump.get(); |
103 pmd2->AddHeapDump("pmd2/heap_dump1", std::move(heap_dump)); | 103 pmd2->AddHeapDump("pmd2/heap_dump1", std::move(heap_dump)); |
104 heap_dump.reset(new TracedValue); | 104 heap_dump.reset(new TracedValue); |
105 heap_dumps_ptr[3] = heap_dump.get(); | 105 heap_dumps_ptr[3] = heap_dump.get(); |
106 pmd2->AddHeapDump("pmd2/heap_dump2", std::move(heap_dump)); | 106 pmd2->AddHeapDump("pmd2/heap_dump2", std::move(heap_dump)); |
107 | 107 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 ASSERT_EQ(heap_dumps_ptr[3], GetHeapDump(*pmd1, "pmd2/heap_dump2")); | 147 ASSERT_EQ(heap_dumps_ptr[3], GetHeapDump(*pmd1, "pmd2/heap_dump2")); |
148 | 148 |
149 // Check that calling AsValueInto() doesn't cause a crash. | 149 // Check that calling AsValueInto() doesn't cause a crash. |
150 traced_value.reset(new TracedValue); | 150 traced_value.reset(new TracedValue); |
151 pmd1->AsValueInto(traced_value.get()); | 151 pmd1->AsValueInto(traced_value.get()); |
152 | 152 |
153 pmd1.reset(); | 153 pmd1.reset(); |
154 } | 154 } |
155 | 155 |
156 TEST(ProcessMemoryDumpTest, Suballocations) { | 156 TEST(ProcessMemoryDumpTest, Suballocations) { |
157 scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr)); | 157 std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr)); |
158 const std::string allocator_dump_name = "fakealloc/allocated_objects"; | 158 const std::string allocator_dump_name = "fakealloc/allocated_objects"; |
159 pmd->CreateAllocatorDump(allocator_dump_name); | 159 pmd->CreateAllocatorDump(allocator_dump_name); |
160 | 160 |
161 // Create one allocation with an auto-assigned guid and mark it as a | 161 // Create one allocation with an auto-assigned guid and mark it as a |
162 // suballocation of "fakealloc/allocated_objects". | 162 // suballocation of "fakealloc/allocated_objects". |
163 auto pic1_dump = pmd->CreateAllocatorDump("picturemanager/picture1"); | 163 auto pic1_dump = pmd->CreateAllocatorDump("picturemanager/picture1"); |
164 pmd->AddSuballocation(pic1_dump->guid(), allocator_dump_name); | 164 pmd->AddSuballocation(pic1_dump->guid(), allocator_dump_name); |
165 | 165 |
166 // Same here, but this time create an allocation with an explicit guid. | 166 // Same here, but this time create an allocation with an explicit guid. |
167 auto pic2_dump = pmd->CreateAllocatorDump("picturemanager/picture2", | 167 auto pic2_dump = pmd->CreateAllocatorDump("picturemanager/picture2", |
(...skipping 16 matching lines...) Expand all Loading... |
184 for (const auto& e : pmd->allocator_dumps_edges()) { | 184 for (const auto& e : pmd->allocator_dumps_edges()) { |
185 found_edge[0] |= (e.source == pic1_dump->guid() && | 185 found_edge[0] |= (e.source == pic1_dump->guid() && |
186 e.target == anon_node_1_it->second->guid()); | 186 e.target == anon_node_1_it->second->guid()); |
187 found_edge[1] |= (e.source == pic2_dump->guid() && | 187 found_edge[1] |= (e.source == pic2_dump->guid() && |
188 e.target == anon_node_2_it->second->guid()); | 188 e.target == anon_node_2_it->second->guid()); |
189 } | 189 } |
190 ASSERT_TRUE(found_edge[0]); | 190 ASSERT_TRUE(found_edge[0]); |
191 ASSERT_TRUE(found_edge[1]); | 191 ASSERT_TRUE(found_edge[1]); |
192 | 192 |
193 // Check that calling AsValueInto() doesn't cause a crash. | 193 // Check that calling AsValueInto() doesn't cause a crash. |
194 scoped_ptr<TracedValue> traced_value(new TracedValue); | 194 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
195 pmd->AsValueInto(traced_value.get()); | 195 pmd->AsValueInto(traced_value.get()); |
196 | 196 |
197 pmd.reset(); | 197 pmd.reset(); |
198 } | 198 } |
199 | 199 |
200 TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) { | 200 TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) { |
201 scoped_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr)); | 201 std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr)); |
202 MemoryAllocatorDumpGuid shared_mad_guid(1); | 202 MemoryAllocatorDumpGuid shared_mad_guid(1); |
203 auto shared_mad1 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); | 203 auto shared_mad1 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); |
204 ASSERT_EQ(shared_mad_guid, shared_mad1->guid()); | 204 ASSERT_EQ(shared_mad_guid, shared_mad1->guid()); |
205 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); | 205 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); |
206 | 206 |
207 auto shared_mad2 = pmd->GetSharedGlobalAllocatorDump(shared_mad_guid); | 207 auto shared_mad2 = pmd->GetSharedGlobalAllocatorDump(shared_mad_guid); |
208 ASSERT_EQ(shared_mad1, shared_mad2); | 208 ASSERT_EQ(shared_mad1, shared_mad2); |
209 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); | 209 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); |
210 | 210 |
211 auto shared_mad3 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); | 211 auto shared_mad3 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); |
212 ASSERT_EQ(shared_mad1, shared_mad3); | 212 ASSERT_EQ(shared_mad1, shared_mad3); |
213 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); | 213 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); |
214 | 214 |
215 auto shared_mad4 = pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid); | 215 auto shared_mad4 = pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid); |
216 ASSERT_EQ(shared_mad1, shared_mad4); | 216 ASSERT_EQ(shared_mad1, shared_mad4); |
217 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); | 217 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); |
218 | 218 |
219 auto shared_mad5 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); | 219 auto shared_mad5 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); |
220 ASSERT_EQ(shared_mad1, shared_mad5); | 220 ASSERT_EQ(shared_mad1, shared_mad5); |
221 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); | 221 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); |
222 } | 222 } |
223 | 223 |
224 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) | 224 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) |
225 TEST(ProcessMemoryDumpTest, CountResidentBytes) { | 225 TEST(ProcessMemoryDumpTest, CountResidentBytes) { |
226 const size_t page_size = ProcessMemoryDump::GetSystemPageSize(); | 226 const size_t page_size = ProcessMemoryDump::GetSystemPageSize(); |
227 | 227 |
228 // Allocate few page of dirty memory and check if it is resident. | 228 // Allocate few page of dirty memory and check if it is resident. |
229 const size_t size1 = 5 * page_size; | 229 const size_t size1 = 5 * page_size; |
230 scoped_ptr<char, base::AlignedFreeDeleter> memory1( | 230 std::unique_ptr<char, base::AlignedFreeDeleter> memory1( |
231 static_cast<char*>(base::AlignedAlloc(size1, page_size))); | 231 static_cast<char*>(base::AlignedAlloc(size1, page_size))); |
232 memset(memory1.get(), 0, size1); | 232 memset(memory1.get(), 0, size1); |
233 size_t res1 = ProcessMemoryDump::CountResidentBytes(memory1.get(), size1); | 233 size_t res1 = ProcessMemoryDump::CountResidentBytes(memory1.get(), size1); |
234 ASSERT_EQ(res1, size1); | 234 ASSERT_EQ(res1, size1); |
235 | 235 |
236 // Allocate a large memory segment (> 8Mib). | 236 // Allocate a large memory segment (> 8Mib). |
237 const size_t kVeryLargeMemorySize = 15 * 1024 * 1024; | 237 const size_t kVeryLargeMemorySize = 15 * 1024 * 1024; |
238 scoped_ptr<char, base::AlignedFreeDeleter> memory2( | 238 std::unique_ptr<char, base::AlignedFreeDeleter> memory2( |
239 static_cast<char*>(base::AlignedAlloc(kVeryLargeMemorySize, page_size))); | 239 static_cast<char*>(base::AlignedAlloc(kVeryLargeMemorySize, page_size))); |
240 memset(memory2.get(), 0, kVeryLargeMemorySize); | 240 memset(memory2.get(), 0, kVeryLargeMemorySize); |
241 size_t res2 = ProcessMemoryDump::CountResidentBytes(memory2.get(), | 241 size_t res2 = ProcessMemoryDump::CountResidentBytes(memory2.get(), |
242 kVeryLargeMemorySize); | 242 kVeryLargeMemorySize); |
243 ASSERT_EQ(res2, kVeryLargeMemorySize); | 243 ASSERT_EQ(res2, kVeryLargeMemorySize); |
244 } | 244 } |
245 #endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) | 245 #endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) |
246 | 246 |
247 } // namespace trace_event | 247 } // namespace trace_event |
248 } // namespace base | 248 } // namespace base |
OLD | NEW |