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