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/memory/ptr_util.h" | 10 #include "base/memory/ptr_util.h" |
11 #include "base/process/process_metrics.h" | 11 #include "base/process/process_metrics.h" |
12 #include "base/trace_event/memory_allocator_dump_guid.h" | 12 #include "base/trace_event/memory_allocator_dump_guid.h" |
13 #include "base/trace_event/memory_infra_background_whitelist.h" | |
13 #include "base/trace_event/trace_event_argument.h" | 14 #include "base/trace_event/trace_event_argument.h" |
14 #include "testing/gtest/include/gtest/gtest.h" | 15 #include "testing/gtest/include/gtest/gtest.h" |
15 | 16 |
16 namespace base { | 17 namespace base { |
17 namespace trace_event { | 18 namespace trace_event { |
18 | 19 |
19 namespace { | 20 namespace { |
21 | |
22 const MemoryDumpArgs kDetailedDumpArgs = {MemoryDumpLevelOfDetail::DETAILED}; | |
23 const char* const kTestDumpNameWhitelist[] = {"WhitelistedTestName", nullptr}; | |
24 | |
20 TracedValue* GetHeapDump(const ProcessMemoryDump& pmd, const char* name) { | 25 TracedValue* GetHeapDump(const ProcessMemoryDump& pmd, const char* name) { |
21 auto it = pmd.heap_dumps().find(name); | 26 auto it = pmd.heap_dumps().find(name); |
22 return it == pmd.heap_dumps().end() ? nullptr : it->second.get(); | 27 return it == pmd.heap_dumps().end() ? nullptr : it->second.get(); |
23 } | 28 } |
29 | |
24 } // namespace | 30 } // namespace |
25 | 31 |
26 TEST(ProcessMemoryDumpTest, Clear) { | 32 TEST(ProcessMemoryDumpTest, Clear) { |
27 std::unique_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(nullptr)); | 33 std::unique_ptr<ProcessMemoryDump> pmd1( |
34 new ProcessMemoryDump(nullptr, kDetailedDumpArgs)); | |
28 pmd1->CreateAllocatorDump("mad1"); | 35 pmd1->CreateAllocatorDump("mad1"); |
29 pmd1->CreateAllocatorDump("mad2"); | 36 pmd1->CreateAllocatorDump("mad2"); |
30 ASSERT_FALSE(pmd1->allocator_dumps().empty()); | 37 ASSERT_FALSE(pmd1->allocator_dumps().empty()); |
31 | 38 |
32 pmd1->process_totals()->set_resident_set_bytes(42); | 39 pmd1->process_totals()->set_resident_set_bytes(42); |
33 pmd1->set_has_process_totals(); | 40 pmd1->set_has_process_totals(); |
34 | 41 |
35 pmd1->process_mmaps()->AddVMRegion(ProcessMemoryMaps::VMRegion()); | 42 pmd1->process_mmaps()->AddVMRegion(ProcessMemoryMaps::VMRegion()); |
36 pmd1->set_has_process_mmaps(); | 43 pmd1->set_has_process_mmaps(); |
37 | 44 |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
85 metrics_by_context[AllocationContext()] = { 1, 1 }; | 92 metrics_by_context[AllocationContext()] = { 1, 1 }; |
86 TraceEventMemoryOverhead overhead; | 93 TraceEventMemoryOverhead overhead; |
87 | 94 |
88 scoped_refptr<MemoryDumpSessionState> session_state = | 95 scoped_refptr<MemoryDumpSessionState> session_state = |
89 new MemoryDumpSessionState; | 96 new MemoryDumpSessionState; |
90 session_state->SetStackFrameDeduplicator( | 97 session_state->SetStackFrameDeduplicator( |
91 WrapUnique(new StackFrameDeduplicator)); | 98 WrapUnique(new StackFrameDeduplicator)); |
92 session_state->SetTypeNameDeduplicator( | 99 session_state->SetTypeNameDeduplicator( |
93 WrapUnique(new TypeNameDeduplicator)); | 100 WrapUnique(new TypeNameDeduplicator)); |
94 std::unique_ptr<ProcessMemoryDump> pmd1( | 101 std::unique_ptr<ProcessMemoryDump> pmd1( |
95 new ProcessMemoryDump(session_state.get())); | 102 new ProcessMemoryDump(session_state.get(), kDetailedDumpArgs)); |
96 auto mad1_1 = pmd1->CreateAllocatorDump("pmd1/mad1"); | 103 auto mad1_1 = pmd1->CreateAllocatorDump("pmd1/mad1"); |
97 auto mad1_2 = pmd1->CreateAllocatorDump("pmd1/mad2"); | 104 auto mad1_2 = pmd1->CreateAllocatorDump("pmd1/mad2"); |
98 pmd1->AddOwnershipEdge(mad1_1->guid(), mad1_2->guid()); | 105 pmd1->AddOwnershipEdge(mad1_1->guid(), mad1_2->guid()); |
99 pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump1"); | 106 pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump1"); |
100 pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump2"); | 107 pmd1->DumpHeapUsage(metrics_by_context, overhead, "pmd1/heap_dump2"); |
101 | 108 |
102 std::unique_ptr<ProcessMemoryDump> pmd2( | 109 std::unique_ptr<ProcessMemoryDump> pmd2( |
103 new ProcessMemoryDump(session_state.get())); | 110 new ProcessMemoryDump(session_state.get(), kDetailedDumpArgs)); |
104 auto mad2_1 = pmd2->CreateAllocatorDump("pmd2/mad1"); | 111 auto mad2_1 = pmd2->CreateAllocatorDump("pmd2/mad1"); |
105 auto mad2_2 = pmd2->CreateAllocatorDump("pmd2/mad2"); | 112 auto mad2_2 = pmd2->CreateAllocatorDump("pmd2/mad2"); |
106 pmd2->AddOwnershipEdge(mad2_1->guid(), mad2_2->guid()); | 113 pmd2->AddOwnershipEdge(mad2_1->guid(), mad2_2->guid()); |
107 pmd2->DumpHeapUsage(metrics_by_context, overhead, "pmd2/heap_dump1"); | 114 pmd2->DumpHeapUsage(metrics_by_context, overhead, "pmd2/heap_dump1"); |
108 pmd2->DumpHeapUsage(metrics_by_context, overhead, "pmd2/heap_dump2"); | 115 pmd2->DumpHeapUsage(metrics_by_context, overhead, "pmd2/heap_dump2"); |
109 | 116 |
110 MemoryAllocatorDumpGuid shared_mad_guid1(1); | 117 MemoryAllocatorDumpGuid shared_mad_guid1(1); |
111 MemoryAllocatorDumpGuid shared_mad_guid2(2); | 118 MemoryAllocatorDumpGuid shared_mad_guid2(2); |
112 auto shared_mad1 = pmd2->CreateSharedGlobalAllocatorDump(shared_mad_guid1); | 119 auto shared_mad1 = pmd2->CreateSharedGlobalAllocatorDump(shared_mad_guid1); |
113 auto shared_mad2 = | 120 auto shared_mad2 = |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
149 ASSERT_TRUE(GetHeapDump(*pmd1, "pmd2/heap_dump2") != nullptr); | 156 ASSERT_TRUE(GetHeapDump(*pmd1, "pmd2/heap_dump2") != nullptr); |
150 | 157 |
151 // Check that calling AsValueInto() doesn't cause a crash. | 158 // Check that calling AsValueInto() doesn't cause a crash. |
152 traced_value.reset(new TracedValue); | 159 traced_value.reset(new TracedValue); |
153 pmd1->AsValueInto(traced_value.get()); | 160 pmd1->AsValueInto(traced_value.get()); |
154 | 161 |
155 pmd1.reset(); | 162 pmd1.reset(); |
156 } | 163 } |
157 | 164 |
158 TEST(ProcessMemoryDumpTest, Suballocations) { | 165 TEST(ProcessMemoryDumpTest, Suballocations) { |
159 std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr)); | 166 std::unique_ptr<ProcessMemoryDump> pmd( |
167 new ProcessMemoryDump(nullptr, kDetailedDumpArgs)); | |
160 const std::string allocator_dump_name = "fakealloc/allocated_objects"; | 168 const std::string allocator_dump_name = "fakealloc/allocated_objects"; |
161 pmd->CreateAllocatorDump(allocator_dump_name); | 169 pmd->CreateAllocatorDump(allocator_dump_name); |
162 | 170 |
163 // Create one allocation with an auto-assigned guid and mark it as a | 171 // Create one allocation with an auto-assigned guid and mark it as a |
164 // suballocation of "fakealloc/allocated_objects". | 172 // suballocation of "fakealloc/allocated_objects". |
165 auto pic1_dump = pmd->CreateAllocatorDump("picturemanager/picture1"); | 173 auto pic1_dump = pmd->CreateAllocatorDump("picturemanager/picture1"); |
166 pmd->AddSuballocation(pic1_dump->guid(), allocator_dump_name); | 174 pmd->AddSuballocation(pic1_dump->guid(), allocator_dump_name); |
167 | 175 |
168 // Same here, but this time create an allocation with an explicit guid. | 176 // Same here, but this time create an allocation with an explicit guid. |
169 auto pic2_dump = pmd->CreateAllocatorDump("picturemanager/picture2", | 177 auto pic2_dump = pmd->CreateAllocatorDump("picturemanager/picture2", |
(...skipping 23 matching lines...) Expand all Loading... | |
193 ASSERT_TRUE(found_edge[1]); | 201 ASSERT_TRUE(found_edge[1]); |
194 | 202 |
195 // Check that calling AsValueInto() doesn't cause a crash. | 203 // Check that calling AsValueInto() doesn't cause a crash. |
196 std::unique_ptr<TracedValue> traced_value(new TracedValue); | 204 std::unique_ptr<TracedValue> traced_value(new TracedValue); |
197 pmd->AsValueInto(traced_value.get()); | 205 pmd->AsValueInto(traced_value.get()); |
198 | 206 |
199 pmd.reset(); | 207 pmd.reset(); |
200 } | 208 } |
201 | 209 |
202 TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) { | 210 TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) { |
203 std::unique_ptr<ProcessMemoryDump> pmd(new ProcessMemoryDump(nullptr)); | 211 std::unique_ptr<ProcessMemoryDump> pmd( |
212 new ProcessMemoryDump(nullptr, kDetailedDumpArgs)); | |
204 MemoryAllocatorDumpGuid shared_mad_guid(1); | 213 MemoryAllocatorDumpGuid shared_mad_guid(1); |
205 auto shared_mad1 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); | 214 auto shared_mad1 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); |
206 ASSERT_EQ(shared_mad_guid, shared_mad1->guid()); | 215 ASSERT_EQ(shared_mad_guid, shared_mad1->guid()); |
207 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); | 216 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); |
208 | 217 |
209 auto shared_mad2 = pmd->GetSharedGlobalAllocatorDump(shared_mad_guid); | 218 auto shared_mad2 = pmd->GetSharedGlobalAllocatorDump(shared_mad_guid); |
210 ASSERT_EQ(shared_mad1, shared_mad2); | 219 ASSERT_EQ(shared_mad1, shared_mad2); |
211 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); | 220 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); |
212 | 221 |
213 auto shared_mad3 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); | 222 auto shared_mad3 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); |
214 ASSERT_EQ(shared_mad1, shared_mad3); | 223 ASSERT_EQ(shared_mad1, shared_mad3); |
215 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); | 224 ASSERT_EQ(MemoryAllocatorDump::Flags::WEAK, shared_mad1->flags()); |
216 | 225 |
217 auto shared_mad4 = pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid); | 226 auto shared_mad4 = pmd->CreateSharedGlobalAllocatorDump(shared_mad_guid); |
218 ASSERT_EQ(shared_mad1, shared_mad4); | 227 ASSERT_EQ(shared_mad1, shared_mad4); |
219 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); | 228 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); |
220 | 229 |
221 auto shared_mad5 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); | 230 auto shared_mad5 = pmd->CreateWeakSharedGlobalAllocatorDump(shared_mad_guid); |
222 ASSERT_EQ(shared_mad1, shared_mad5); | 231 ASSERT_EQ(shared_mad1, shared_mad5); |
223 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); | 232 ASSERT_EQ(MemoryAllocatorDump::Flags::DEFAULT, shared_mad1->flags()); |
224 } | 233 } |
225 | 234 |
235 TEST(ProcessMemoryDumpTest, BackgroundModeTest) { | |
236 MemoryDumpArgs background_args = {MemoryDumpLevelOfDetail::BACKGROUND}; | |
237 std::unique_ptr<ProcessMemoryDump> pmd( | |
238 new ProcessMemoryDump(nullptr, background_args)); | |
239 ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = true; | |
240 SetAllocatorDumpNameWhitelistForTesting(kTestDumpNameWhitelist); | |
241 MemoryAllocatorDump* black_hole_mad = pmd->GetBlackHoleMad(); | |
242 | |
243 // Invalid dump names. | |
244 EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("NotWhitelistedTestName")); | |
245 EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("TestName")); | |
246 EXPECT_EQ(black_hole_mad, pmd->CreateAllocatorDump("Whitelisted/Test")); | |
247 EXPECT_EQ(black_hole_mad, | |
248 pmd->CreateAllocatorDump("Not/Whitelisted/TestName")); | |
249 EXPECT_EQ(black_hole_mad, | |
250 pmd->CreateAllocatorDump("Whitelisted/TestName/Google")); | |
251 EXPECT_EQ(black_hole_mad, | |
252 pmd->CreateAllocatorDump("Whitelisted/TestName/0x1a2Google")); | |
253 EXPECT_EQ(black_hole_mad, | |
254 pmd->CreateAllocatorDump("Whitelisted/TestName/__12/Google")); | |
255 | |
256 // Global dumps. | |
257 MemoryAllocatorDumpGuid guid(1); | |
258 EXPECT_EQ(black_hole_mad, pmd->CreateSharedGlobalAllocatorDump(guid)); | |
259 EXPECT_EQ(black_hole_mad, pmd->CreateWeakSharedGlobalAllocatorDump(guid)); | |
260 EXPECT_EQ(black_hole_mad, pmd->GetSharedGlobalAllocatorDump(guid)); | |
261 | |
262 // Suballocations. | |
263 pmd->AddSuballocation(guid, "malloc/allocated_objects"); | |
264 EXPECT_EQ(0u, pmd->allocator_dumps_edges_.size()); | |
265 EXPECT_EQ(0u, pmd->allocator_dumps_.size()); | |
266 | |
267 // Valid dump names. | |
268 EXPECT_NE(black_hole_mad, pmd->CreateAllocatorDump("WhitelistedTestName")); | |
269 EXPECT_NE(black_hole_mad, | |
270 pmd->CreateAllocatorDump("Whitelisted/TestName/0xA1b2")); | |
Primiano Tucci (use gerrit)
2016/06/03 16:24:36
small change, By looking at this test I just reali
ssid
2016/06/04 00:26:58
There is no way to avoid awkwardness.
Right now if
| |
271 EXPECT_NE(black_hole_mad, | |
272 pmd->CreateAllocatorDump("Whitelisted/TestName_123/0xab")); | |
273 EXPECT_NE(black_hole_mad, | |
274 pmd->CreateAllocatorDump("Whitelisted_12/0xaB/TestName")); | |
275 | |
276 // GetAllocatorDump is consistent. | |
277 EXPECT_EQ(black_hole_mad, pmd->GetAllocatorDump("NotWhitelistedTestName")); | |
278 auto mad = pmd->GetAllocatorDump("WhitelistedTestName"); | |
279 EXPECT_NE(black_hole_mad, mad); | |
280 } | |
281 | |
226 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) | 282 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) |
227 TEST(ProcessMemoryDumpTest, CountResidentBytes) { | 283 TEST(ProcessMemoryDumpTest, CountResidentBytes) { |
228 const size_t page_size = ProcessMemoryDump::GetSystemPageSize(); | 284 const size_t page_size = ProcessMemoryDump::GetSystemPageSize(); |
229 | 285 |
230 // Allocate few page of dirty memory and check if it is resident. | 286 // Allocate few page of dirty memory and check if it is resident. |
231 const size_t size1 = 5 * page_size; | 287 const size_t size1 = 5 * page_size; |
232 std::unique_ptr<char, base::AlignedFreeDeleter> memory1( | 288 std::unique_ptr<char, base::AlignedFreeDeleter> memory1( |
233 static_cast<char*>(base::AlignedAlloc(size1, page_size))); | 289 static_cast<char*>(base::AlignedAlloc(size1, page_size))); |
234 memset(memory1.get(), 0, size1); | 290 memset(memory1.get(), 0, size1); |
235 size_t res1 = ProcessMemoryDump::CountResidentBytes(memory1.get(), size1); | 291 size_t res1 = ProcessMemoryDump::CountResidentBytes(memory1.get(), size1); |
236 ASSERT_EQ(res1, size1); | 292 ASSERT_EQ(res1, size1); |
237 | 293 |
238 // Allocate a large memory segment (> 8Mib). | 294 // Allocate a large memory segment (> 8Mib). |
239 const size_t kVeryLargeMemorySize = 15 * 1024 * 1024; | 295 const size_t kVeryLargeMemorySize = 15 * 1024 * 1024; |
240 std::unique_ptr<char, base::AlignedFreeDeleter> memory2( | 296 std::unique_ptr<char, base::AlignedFreeDeleter> memory2( |
241 static_cast<char*>(base::AlignedAlloc(kVeryLargeMemorySize, page_size))); | 297 static_cast<char*>(base::AlignedAlloc(kVeryLargeMemorySize, page_size))); |
242 memset(memory2.get(), 0, kVeryLargeMemorySize); | 298 memset(memory2.get(), 0, kVeryLargeMemorySize); |
243 size_t res2 = ProcessMemoryDump::CountResidentBytes(memory2.get(), | 299 size_t res2 = ProcessMemoryDump::CountResidentBytes(memory2.get(), |
244 kVeryLargeMemorySize); | 300 kVeryLargeMemorySize); |
245 ASSERT_EQ(res2, kVeryLargeMemorySize); | 301 ASSERT_EQ(res2, kVeryLargeMemorySize); |
246 } | 302 } |
247 #endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) | 303 #endif // defined(COUNT_RESIDENT_BYTES_SUPPORTED) |
248 | 304 |
249 } // namespace trace_event | 305 } // namespace trace_event |
250 } // namespace base | 306 } // namespace base |
OLD | NEW |