Chromium Code Reviews| 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 "platform/PartitionAllocMemoryDumpProvider.h" | 5 #include "platform/PartitionAllocMemoryDumpProvider.h" |
| 6 | 6 |
| 7 #include "base/strings/stringprintf.h" | |
| 7 #include "base/trace_event/heap_profiler_allocation_context.h" | 8 #include "base/trace_event/heap_profiler_allocation_context.h" |
| 8 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" | 9 #include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
| 9 #include "base/trace_event/heap_profiler_allocation_register.h" | 10 #include "base/trace_event/heap_profiler_allocation_register.h" |
| 10 #include "base/trace_event/process_memory_dump.h" | 11 #include "base/trace_event/process_memory_dump.h" |
| 11 #include "base/trace_event/trace_event_memory_overhead.h" | 12 #include "base/trace_event/trace_event_memory_overhead.h" |
| 12 #include "public/platform/WebMemoryAllocatorDump.h" | |
| 13 #include "public/platform/WebProcessMemoryDump.h" | |
| 14 #include "wtf/allocator/Partitions.h" | 13 #include "wtf/allocator/Partitions.h" |
| 15 #include "wtf/text/WTFString.h" | 14 #include "wtf/text/WTFString.h" |
| 16 | 15 |
| 17 namespace blink { | 16 namespace blink { |
| 18 | 17 |
| 19 namespace { | 18 namespace { |
| 20 | 19 |
| 21 using namespace WTF; | 20 using namespace WTF; |
| 22 | 21 |
| 23 void reportAllocation(void* address, size_t size, const char* typeName) | 22 void reportAllocation(void* address, size_t size, const char* typeName) |
| 24 { | 23 { |
| 25 PartitionAllocMemoryDumpProvider::instance()->insert(address, size, typeName ); | 24 PartitionAllocMemoryDumpProvider::instance()->insert(address, size, typeName ); |
| 26 } | 25 } |
| 27 | 26 |
| 28 void reportFree(void* address) | 27 void reportFree(void* address) |
| 29 { | 28 { |
| 30 PartitionAllocMemoryDumpProvider::instance()->remove(address); | 29 PartitionAllocMemoryDumpProvider::instance()->remove(address); |
| 31 } | 30 } |
| 32 | 31 |
| 33 const char kPartitionAllocDumpName[] = "partition_alloc"; | 32 const char kPartitionAllocDumpName[] = "partition_alloc"; |
| 34 const char kPartitionsDumpName[] = "partitions"; | 33 const char kPartitionsDumpName[] = "partitions"; |
| 35 | 34 |
| 36 String getPartitionDumpName(const char* partitionName) | 35 std::string getPartitionDumpName(const char* partitionName) |
| 37 { | 36 { |
| 38 return String::format("%s/%s/%s", kPartitionAllocDumpName, kPartitionsDumpNa me, partitionName); | 37 return base::StringPrintf("%s/%s/%s", kPartitionAllocDumpName, kPartitionsDu mpName, partitionName); |
| 39 } | 38 } |
| 40 | 39 |
| 41 // This class is used to invert the dependency of PartitionAlloc on the | 40 // This class is used to invert the dependency of PartitionAlloc on the |
| 42 // PartitionAllocMemoryDumpProvider. This implements an interface that will | 41 // PartitionAllocMemoryDumpProvider. This implements an interface that will |
| 43 // be called with memory statistics for each bucket in the allocator. | 42 // be called with memory statistics for each bucket in the allocator. |
| 44 class PartitionStatsDumperImpl final : public PartitionStatsDumper { | 43 class PartitionStatsDumperImpl final : public PartitionStatsDumper { |
| 45 DISALLOW_NEW(); | 44 DISALLOW_NEW(); |
| 46 WTF_MAKE_NONCOPYABLE(PartitionStatsDumperImpl); | 45 WTF_MAKE_NONCOPYABLE(PartitionStatsDumperImpl); |
| 47 public: | 46 public: |
| 48 PartitionStatsDumperImpl(WebProcessMemoryDump* memoryDump, WebMemoryDumpLeve lOfDetail levelOfDetail) | 47 PartitionStatsDumperImpl(base::trace_event::ProcessMemoryDump* memoryDump, b ase::trace_event::MemoryDumpLevelOfDetail levelOfDetail) |
| 49 : m_memoryDump(memoryDump) | 48 : m_memoryDump(memoryDump) |
| 50 , m_uid(0) | 49 , m_uid(0) |
| 51 , m_totalActiveBytes(0) | 50 , m_totalActiveBytes(0) |
| 52 { | 51 { |
| 53 } | 52 } |
| 54 | 53 |
| 55 // PartitionStatsDumper implementation. | 54 // PartitionStatsDumper implementation. |
| 56 void partitionDumpTotals(const char* partitionName, const PartitionMemorySta ts*) override; | 55 void partitionDumpTotals(const char* partitionName, const PartitionMemorySta ts*) override; |
| 57 void partitionsDumpBucketStats(const char* partitionName, const PartitionBuc ketMemoryStats*) override; | 56 void partitionsDumpBucketStats(const char* partitionName, const PartitionBuc ketMemoryStats*) override; |
| 58 | 57 |
| 59 size_t totalActiveBytes() const { return m_totalActiveBytes; } | 58 size_t totalActiveBytes() const { return m_totalActiveBytes; } |
| 60 | 59 |
| 61 private: | 60 private: |
| 62 WebProcessMemoryDump* m_memoryDump; | 61 base::trace_event::ProcessMemoryDump* m_memoryDump; |
| 63 unsigned long m_uid; | 62 unsigned long m_uid; |
| 64 size_t m_totalActiveBytes; | 63 size_t m_totalActiveBytes; |
| 65 }; | 64 }; |
| 66 | 65 |
| 67 void PartitionStatsDumperImpl::partitionDumpTotals(const char* partitionName, co nst PartitionMemoryStats* memoryStats) | 66 void PartitionStatsDumperImpl::partitionDumpTotals(const char* partitionName, co nst PartitionMemoryStats* memoryStats) |
| 68 { | 67 { |
| 69 m_totalActiveBytes += memoryStats->totalActiveBytes; | 68 m_totalActiveBytes += memoryStats->totalActiveBytes; |
| 70 String dumpName = getPartitionDumpName(partitionName); | 69 std::string dumpName = getPartitionDumpName(partitionName); |
| 71 WebMemoryAllocatorDump* allocatorDump = m_memoryDump->createMemoryAllocatorD ump(dumpName); | 70 base::trace_event::MemoryAllocatorDump* allocatorDump = m_memoryDump->Create AllocatorDump(dumpName); |
| 72 allocatorDump->addScalar("size", "bytes", memoryStats->totalResidentBytes); | 71 allocatorDump->AddScalar("size", "bytes", memoryStats->totalResidentBytes); |
| 73 allocatorDump->addScalar("allocated_objects_size", "bytes", memoryStats->tot alActiveBytes); | 72 allocatorDump->AddScalar("allocated_objects_size", "bytes", memoryStats->tot alActiveBytes); |
| 74 allocatorDump->addScalar("virtual_size", "bytes", memoryStats->totalMmappedB ytes); | 73 allocatorDump->AddScalar("virtual_size", "bytes", memoryStats->totalMmappedB ytes); |
| 75 allocatorDump->addScalar("virtual_committed_size", "bytes", memoryStats->tot alCommittedBytes); | 74 allocatorDump->AddScalar("virtual_committed_size", "bytes", memoryStats->tot alCommittedBytes); |
| 76 allocatorDump->addScalar("decommittable_size", "bytes", memoryStats->totalDe committableBytes); | 75 allocatorDump->AddScalar("decommittable_size", "bytes", memoryStats->totalDe committableBytes); |
| 77 allocatorDump->addScalar("discardable_size", "bytes", memoryStats->totalDisc ardableBytes); | 76 allocatorDump->AddScalar("discardable_size", "bytes", memoryStats->totalDisc ardableBytes); |
| 78 } | 77 } |
| 79 | 78 |
| 80 void PartitionStatsDumperImpl::partitionsDumpBucketStats(const char* partitionNa me, const PartitionBucketMemoryStats* memoryStats) | 79 void PartitionStatsDumperImpl::partitionsDumpBucketStats(const char* partitionNa me, const PartitionBucketMemoryStats* memoryStats) |
| 81 { | 80 { |
| 82 ASSERT(memoryStats->isValid); | 81 ASSERT(memoryStats->isValid); |
| 83 String dumpName = getPartitionDumpName(partitionName); | 82 std::string dumpName = getPartitionDumpName(partitionName); |
| 84 if (memoryStats->isDirectMap) | 83 if (memoryStats->isDirectMap) |
| 85 dumpName.append(String::format("/directMap_%lu", ++m_uid)); | 84 dumpName.append(base::StringPrintf("/directMap_%lu", ++m_uid)); |
| 86 else | 85 else |
| 87 dumpName.append(String::format("/bucket_%u", static_cast<unsigned>(memor yStats->bucketSlotSize))); | 86 dumpName.append(base::StringPrintf("/bucket_%u", static_cast<unsigned>(m emoryStats->bucketSlotSize))); |
| 88 | 87 |
| 89 WebMemoryAllocatorDump* allocatorDump = m_memoryDump->createMemoryAllocatorD ump(dumpName); | 88 base::trace_event::MemoryAllocatorDump* allocatorDump = m_memoryDump->Create AllocatorDump(dumpName); |
| 90 allocatorDump->addScalar("size", "bytes", memoryStats->residentBytes); | 89 allocatorDump->AddScalar("size", "bytes", memoryStats->residentBytes); |
| 91 allocatorDump->addScalar("allocated_objects_size", "bytes", memoryStats->act iveBytes); | 90 allocatorDump->AddScalar("allocated_objects_size", "bytes", memoryStats->act iveBytes); |
| 92 allocatorDump->addScalar("slot_size", "bytes", memoryStats->bucketSlotSize); | 91 allocatorDump->AddScalar("slot_size", "bytes", memoryStats->bucketSlotSize); |
| 93 allocatorDump->addScalar("decommittable_size", "bytes", memoryStats->decommi ttableBytes); | 92 allocatorDump->AddScalar("decommittable_size", "bytes", memoryStats->decommi ttableBytes); |
| 94 allocatorDump->addScalar("discardable_size", "bytes", memoryStats->discardab leBytes); | 93 allocatorDump->AddScalar("discardable_size", "bytes", memoryStats->discardab leBytes); |
| 95 allocatorDump->addScalar("total_pages_size", "bytes", memoryStats->allocated PageSize); | 94 allocatorDump->AddScalar("total_pages_size", "bytes", memoryStats->allocated PageSize); |
| 96 allocatorDump->addScalar("active_pages", "objects", memoryStats->numActivePa ges); | 95 allocatorDump->AddScalar("active_pages", "objects", memoryStats->numActivePa ges); |
| 97 allocatorDump->addScalar("full_pages", "objects", memoryStats->numFullPages) ; | 96 allocatorDump->AddScalar("full_pages", "objects", memoryStats->numFullPages) ; |
| 98 allocatorDump->addScalar("empty_pages", "objects", memoryStats->numEmptyPage s); | 97 allocatorDump->AddScalar("empty_pages", "objects", memoryStats->numEmptyPage s); |
| 99 allocatorDump->addScalar("decommitted_pages", "objects", memoryStats->numDec ommittedPages); | 98 allocatorDump->AddScalar("decommitted_pages", "objects", memoryStats->numDec ommittedPages); |
| 100 } | 99 } |
| 101 | 100 |
| 102 } // namespace | 101 } // namespace |
| 103 | 102 |
| 104 PartitionAllocMemoryDumpProvider* PartitionAllocMemoryDumpProvider::instance() | 103 PartitionAllocMemoryDumpProvider* PartitionAllocMemoryDumpProvider::instance() |
| 105 { | 104 { |
| 106 DEFINE_STATIC_LOCAL(PartitionAllocMemoryDumpProvider, instance, ()); | 105 DEFINE_STATIC_LOCAL(PartitionAllocMemoryDumpProvider, instance, ()); |
| 107 return &instance; | 106 return &instance; |
| 108 } | 107 } |
| 109 | 108 |
| 110 bool PartitionAllocMemoryDumpProvider::onMemoryDump(WebMemoryDumpLevelOfDetail l evelOfDetail, WebProcessMemoryDump* memoryDump) | 109 bool PartitionAllocMemoryDumpProvider::OnMemoryDump(const base::trace_event::Mem oryDumpArgs& args, base::trace_event::ProcessMemoryDump* memoryDump) |
| 111 { | 110 { |
| 111 base::trace_event::MemoryDumpLevelOfDetail levelOfDetail = args.level_of_det ail; | |
| 112 if (m_isHeapProfilingEnabled) { | 112 if (m_isHeapProfilingEnabled) { |
| 113 // Overhead should always be reported, regardless of light vs. heavy. | 113 // Overhead should always be reported, regardless of light vs. heavy. |
| 114 base::trace_event::TraceEventMemoryOverhead overhead; | 114 base::trace_event::TraceEventMemoryOverhead overhead; |
| 115 base::hash_map<base::trace_event::AllocationContext, base::trace_event:: AllocationMetrics> metricsByContext; | 115 base::hash_map<base::trace_event::AllocationContext, base::trace_event:: AllocationMetrics> metricsByContext; |
| 116 { | 116 { |
| 117 MutexLocker locker(m_allocationRegisterMutex); | 117 MutexLocker locker(m_allocationRegisterMutex); |
| 118 // Dump only the overhead estimation in non-detailed dumps. | 118 // Dump only the overhead estimation in non-detailed dumps. |
| 119 if (levelOfDetail == WebMemoryDumpLevelOfDetail::Detailed) { | 119 if (levelOfDetail == base::trace_event::MemoryDumpLevelOfDetail::DET AILED) { |
|
Primiano Tucci (use gerrit)
2016/04/22 13:05:57
maybe a "using base::trace_event::MemoryDumpLevelO
bashi
2016/04/24 23:33:12
Done.
| |
| 120 for (const auto& allocSize : *m_allocationRegister) { | 120 for (const auto& allocSize : *m_allocationRegister) { |
| 121 base::trace_event::AllocationMetrics& metrics = metricsByCon text[allocSize.context]; | 121 base::trace_event::AllocationMetrics& metrics = metricsByCon text[allocSize.context]; |
| 122 metrics.size += allocSize.size; | 122 metrics.size += allocSize.size; |
| 123 metrics.count++; | 123 metrics.count++; |
| 124 } | 124 } |
| 125 } | 125 } |
| 126 m_allocationRegister->EstimateTraceMemoryOverhead(&overhead); | 126 m_allocationRegister->EstimateTraceMemoryOverhead(&overhead); |
| 127 } | 127 } |
| 128 memoryDump->dumpHeapUsage(metricsByContext, overhead, "partition_alloc") ; | 128 memoryDump->DumpHeapUsage(metricsByContext, overhead, "partition_alloc") ; |
| 129 } | 129 } |
| 130 | 130 |
| 131 PartitionStatsDumperImpl partitionStatsDumper(memoryDump, levelOfDetail); | 131 PartitionStatsDumperImpl partitionStatsDumper(memoryDump, levelOfDetail); |
| 132 | 132 |
| 133 WebMemoryAllocatorDump* partitionsDump = memoryDump->createMemoryAllocatorDu mp( | 133 base::trace_event::MemoryAllocatorDump* partitionsDump = memoryDump->CreateA llocatorDump( |
| 134 String::format("%s/%s", kPartitionAllocDumpName, kPartitionsDumpName)); | 134 base::StringPrintf("%s/%s", kPartitionAllocDumpName, kPartitionsDumpName )); |
| 135 | 135 |
| 136 // This method calls memoryStats.partitionsDumpBucketStats with memory stati stics. | 136 // This method calls memoryStats.partitionsDumpBucketStats with memory stati stics. |
| 137 WTF::Partitions::dumpMemoryStats(levelOfDetail == WebMemoryDumpLevelOfDetail ::Light, &partitionStatsDumper); | 137 WTF::Partitions::dumpMemoryStats(levelOfDetail == base::trace_event::MemoryD umpLevelOfDetail::LIGHT, &partitionStatsDumper); |
| 138 | 138 |
| 139 WebMemoryAllocatorDump* allocatedObjectsDump = memoryDump->createMemoryAlloc atorDump(String(Partitions::kAllocatedObjectPoolName)); | 139 base::trace_event::MemoryAllocatorDump* allocatedObjectsDump = memoryDump->C reateAllocatorDump(Partitions::kAllocatedObjectPoolName); |
| 140 allocatedObjectsDump->addScalar("size", "bytes", partitionStatsDumper.totalA ctiveBytes()); | 140 allocatedObjectsDump->AddScalar("size", "bytes", partitionStatsDumper.totalA ctiveBytes()); |
| 141 memoryDump->addOwnershipEdge(allocatedObjectsDump->guid(), partitionsDump->g uid()); | 141 memoryDump->AddOwnershipEdge(allocatedObjectsDump->guid(), partitionsDump->g uid()); |
| 142 | 142 |
| 143 return true; | 143 return true; |
| 144 } | 144 } |
| 145 | 145 |
| 146 // |m_allocationRegister| should be initialized only when necessary to avoid was te of memory. | 146 // |m_allocationRegister| should be initialized only when necessary to avoid was te of memory. |
| 147 PartitionAllocMemoryDumpProvider::PartitionAllocMemoryDumpProvider() | 147 PartitionAllocMemoryDumpProvider::PartitionAllocMemoryDumpProvider() |
| 148 : m_allocationRegister(nullptr) | 148 : m_allocationRegister(nullptr) |
| 149 , m_isHeapProfilingEnabled(false) | 149 , m_isHeapProfilingEnabled(false) |
| 150 { | 150 { |
| 151 } | 151 } |
| 152 | 152 |
| 153 PartitionAllocMemoryDumpProvider::~PartitionAllocMemoryDumpProvider() | 153 PartitionAllocMemoryDumpProvider::~PartitionAllocMemoryDumpProvider() |
| 154 { | 154 { |
| 155 } | 155 } |
| 156 | 156 |
| 157 void PartitionAllocMemoryDumpProvider::onHeapProfilingEnabled(bool enabled) | 157 void PartitionAllocMemoryDumpProvider::OnHeapProfilingEnabled(bool enabled) |
| 158 { | 158 { |
| 159 if (enabled) { | 159 if (enabled) { |
| 160 { | 160 { |
| 161 MutexLocker locker(m_allocationRegisterMutex); | 161 MutexLocker locker(m_allocationRegisterMutex); |
| 162 if (!m_allocationRegister) | 162 if (!m_allocationRegister) |
| 163 m_allocationRegister = adoptPtr(new base::trace_event::Allocatio nRegister()); | 163 m_allocationRegister.reset(new base::trace_event::AllocationRegi ster()); |
| 164 } | 164 } |
| 165 PartitionAllocHooks::setAllocationHook(reportAllocation); | 165 PartitionAllocHooks::setAllocationHook(reportAllocation); |
| 166 PartitionAllocHooks::setFreeHook(reportFree); | 166 PartitionAllocHooks::setFreeHook(reportFree); |
| 167 } else { | 167 } else { |
| 168 PartitionAllocHooks::setAllocationHook(nullptr); | 168 PartitionAllocHooks::setAllocationHook(nullptr); |
| 169 PartitionAllocHooks::setFreeHook(nullptr); | 169 PartitionAllocHooks::setFreeHook(nullptr); |
| 170 } | 170 } |
| 171 m_isHeapProfilingEnabled = enabled; | 171 m_isHeapProfilingEnabled = enabled; |
| 172 } | 172 } |
| 173 | 173 |
| 174 void PartitionAllocMemoryDumpProvider::insert(void* address, size_t size, const char* typeName) | 174 void PartitionAllocMemoryDumpProvider::insert(void* address, size_t size, const char* typeName) |
| 175 { | 175 { |
| 176 base::trace_event::AllocationContext context = base::trace_event::Allocation ContextTracker::GetInstanceForCurrentThread()->GetContextSnapshot(); | 176 base::trace_event::AllocationContext context = base::trace_event::Allocation ContextTracker::GetInstanceForCurrentThread()->GetContextSnapshot(); |
| 177 context.type_name = typeName; | 177 context.type_name = typeName; |
| 178 MutexLocker locker(m_allocationRegisterMutex); | 178 MutexLocker locker(m_allocationRegisterMutex); |
| 179 if (m_allocationRegister) | 179 if (m_allocationRegister) |
| 180 m_allocationRegister->Insert(address, size, context); | 180 m_allocationRegister->Insert(address, size, context); |
| 181 } | 181 } |
| 182 | 182 |
| 183 void PartitionAllocMemoryDumpProvider::remove(void* address) | 183 void PartitionAllocMemoryDumpProvider::remove(void* address) |
| 184 { | 184 { |
| 185 MutexLocker locker(m_allocationRegisterMutex); | 185 MutexLocker locker(m_allocationRegisterMutex); |
| 186 if (m_allocationRegister) | 186 if (m_allocationRegister) |
| 187 m_allocationRegister->Remove(address); | 187 m_allocationRegister->Remove(address); |
| 188 } | 188 } |
| 189 | 189 |
| 190 } // namespace blink | 190 } // namespace blink |
| OLD | NEW |