Index: skia/ext/skia_memory_dump_provider.cc |
diff --git a/skia/ext/skia_memory_dump_provider.cc b/skia/ext/skia_memory_dump_provider.cc |
index e0767526beacb4c293351dc9b401fbd7df7fabc1..5f09afb906bd47703f653788990ebfe5592188cc 100644 |
--- a/skia/ext/skia_memory_dump_provider.cc |
+++ b/skia/ext/skia_memory_dump_provider.cc |
@@ -4,6 +4,8 @@ |
#include "skia_memory_dump_provider.h" |
+#include "base/trace_event/heap_profiler_allocation_context_tracker.h" |
+#include "base/trace_event/heap_profiler_heap_dump_writer.cc" |
#include "base/trace_event/memory_allocator_dump.h" |
#include "base/trace_event/memory_dump_manager.h" |
#include "base/trace_event/process_memory_dump.h" |
@@ -12,6 +14,21 @@ |
namespace skia { |
+namespace { |
+ |
+void ReportAllocation(void* address, size_t size, const char* type_name) { |
+ SkiaMemoryDumpProvider::GetInstance()->Insert(address, size, type_name); |
+} |
+ |
+void ReportFree(void* address) { |
+ SkiaMemoryDumpProvider::GetInstance()->Remove(address); |
+} |
+ |
+} // namespace |
+ |
+SkiaAllocHooks::AllocationHook* SkiaAllocHooks::allocation_hook_ = nullptr; |
+SkiaAllocHooks::FreeHook* SkiaAllocHooks::free_hook_ = nullptr; |
+ |
// static |
SkiaMemoryDumpProvider* SkiaMemoryDumpProvider::GetInstance() { |
return base::Singleton< |
@@ -19,7 +36,9 @@ SkiaMemoryDumpProvider* SkiaMemoryDumpProvider::GetInstance() { |
base::LeakySingletonTraits<SkiaMemoryDumpProvider>>::get(); |
} |
-SkiaMemoryDumpProvider::SkiaMemoryDumpProvider() {} |
+SkiaMemoryDumpProvider::SkiaMemoryDumpProvider() |
+ : is_heap_profiling_enabled_(false) { |
+} |
SkiaMemoryDumpProvider::~SkiaMemoryDumpProvider() {} |
@@ -30,7 +49,89 @@ bool SkiaMemoryDumpProvider::OnMemoryDump( |
process_memory_dump); |
SkGraphics::DumpMemoryStatistics(&skia_dumper); |
+ if (is_heap_profiling_enabled_) { |
+ int total_size = 0; |
+ /*if (args.level_of_detail == |
+ base::trace_event::MemoryDumpLevelOfDetail::DETAILED) {*/ |
+ if (true) { |
+ base::trace_event::TraceEventMemoryOverhead overhead; |
+ base::hash_map<base::trace_event::AllocationContext, size_t> |
+ bytes_by_context; |
+ { |
+ base::AutoLock scoped_lock(lock_); |
+ for (const auto& alloc_size : *allocation_register_) { |
+ bytes_by_context[alloc_size.context] += alloc_size.size; |
+ total_size += alloc_size.size; |
+ } |
+ allocation_register_->EstimateTraceMemoryOverhead(&overhead); |
+ } |
+ |
+ // Copied from WebProcessMemoryDumpImpl::dumpHeapUsage |
+ const char* allocator_name = "skia"; |
+ if (!bytes_by_context.empty()) { |
+ scoped_refptr<base::trace_event::MemoryDumpSessionState> session_state = |
+ process_memory_dump->session_state(); |
+ scoped_ptr<base::trace_event::TracedValue> heap_dump = |
+ ExportHeapDump(bytes_by_context, |
+ session_state->stack_frame_deduplicator(), |
+ session_state->type_name_deduplicator()); |
+ process_memory_dump->AddHeapDump(allocator_name, std::move(heap_dump)); |
+ } |
+ std::string base_name = |
+ base::StringPrintf("tracing/heap_profiler_%s", allocator_name); |
+ overhead.DumpInto(base_name.c_str(), process_memory_dump); |
+ } else { |
+ int total_size = 0; |
+ { |
+ base::AutoLock scoped_lock(lock_); |
+ for (const auto& alloc_size : *allocation_register_) { |
+ total_size += alloc_size.size; |
+ } |
+ } |
+ } |
+ |
+ const char* dump_name = "skia/sk_malloc"; |
+ skia_dumper.dumpNumericValue(dump_name, "size", "bytes", total_size); |
+ skia_dumper.setMemoryBacking(dump_name, "malloc", nullptr); |
+ } |
+ |
return true; |
} |
+void SkiaMemoryDumpProvider::OnHeapProfilingEnabled(bool enabled) { |
+ if (enabled) { |
+ { |
+ base::AutoLock scoped_lock(lock_); |
+ if (!allocation_register_) { |
+ allocation_register_ = make_scoped_ptr( |
+ new base::trace_event::AllocationRegister()); |
+ } |
+ } |
+ SkiaAllocHooks::SetAllocationHook(ReportAllocation); |
+ SkiaAllocHooks::SetFreeHook(ReportFree); |
+ } else { |
+ SkiaAllocHooks::SetAllocationHook(nullptr); |
+ SkiaAllocHooks::SetFreeHook(nullptr); |
+ } |
+ is_heap_profiling_enabled_ = enabled; |
+} |
+ |
+void SkiaMemoryDumpProvider::Insert(void* address, size_t size, |
+ const char* type_name) { |
+ base::trace_event::AllocationContext context = |
+ base::trace_event::AllocationContextTracker::GetInstanceForCurrentThread()->GetContextSnapshot(); |
+ context.type_name = type_name; |
+ base::AutoLock scoped_lock(lock_); |
+ if (allocation_register_) { |
+ allocation_register_->Insert(address, size, context); |
+ } |
+} |
+ |
+void SkiaMemoryDumpProvider::Remove(void* address) { |
+ base::AutoLock scoped_lock(lock_); |
+ if (allocation_register_) { |
+ allocation_register_->Remove(address); |
+ } |
+} |
+ |
} // namespace skia |