| Index: base/trace_event/memory_profiler_heap_dumper.cc
|
| diff --git a/base/trace_event/memory_profiler_heap_dumper.cc b/base/trace_event/memory_profiler_heap_dumper.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..03647e069edf306ace2fee972952f64d85cbe6e4
|
| --- /dev/null
|
| +++ b/base/trace_event/memory_profiler_heap_dumper.cc
|
| @@ -0,0 +1,83 @@
|
| +// Copyright 2015 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/trace_event/memory_profiler_heap_dumper.h"
|
| +
|
| +#include <numeric>
|
| +
|
| +#include "base/format_macros.h"
|
| +#include "base/strings/stringprintf.h"
|
| +#include "base/trace_event/memory_profiler_allocation_register.h"
|
| +
|
| +namespace base {
|
| +namespace trace_event {
|
| +
|
| +namespace {
|
| +
|
| +template <typename T>
|
| +bool PairSizeGt(const std::pair<T, size_t>& lhs,
|
| + const std::pair<T, size_t>& rhs) {
|
| + return lhs.second > rhs.second;
|
| +}
|
| +
|
| +template <typename T>
|
| +size_t PairSizeAdd(size_t acc, const std::pair<T, size_t>& rhs) {
|
| + return acc + rhs.second;
|
| +}
|
| +
|
| +} // namespace
|
| +
|
| +HeapDumper::HeapDumper(scoped_refptr<TracedValue> traced_value,
|
| + StackFrameDeduplicator* sf_deduplicator)
|
| + : traced_value_(traced_value), sf_deduplicator_(sf_deduplicator) {}
|
| +HeapDumper::~HeapDumper() {}
|
| +
|
| +void HeapDumper::Fill(const AllocationRegister& allocation_register) {
|
| + for (auto alloc : allocation_register)
|
| + acc_by_backtrace_[alloc.context.backtrace] += alloc.size;
|
| +}
|
| +
|
| +void HeapDumper::WriteHeapDump() {
|
| + // Sort the backtraces by size in descending order.
|
| + std::vector<std::pair<Backtrace, size_t>> sorted_by_backtrace;
|
| +
|
| + std::copy(acc_by_backtrace_.begin(), acc_by_backtrace_.end(),
|
| + std::back_inserter(sorted_by_backtrace));
|
| + std::sort(sorted_by_backtrace.begin(), sorted_by_backtrace.end(),
|
| + PairSizeGt<Backtrace>);
|
| +
|
| + traced_value_->BeginArray("heap");
|
| +
|
| + // The global size, no column specified.
|
| + {
|
| + size_t total_size =
|
| + std::accumulate(sorted_by_backtrace.begin(), sorted_by_backtrace.end(),
|
| + size_t(0), PairSizeAdd<Backtrace>);
|
| + traced_value_->BeginDictionary();
|
| + WriteSize(total_size);
|
| + traced_value_->EndDictionary();
|
| + }
|
| +
|
| + // Size per backtrace.
|
| + for (auto bt_sz = sorted_by_backtrace.begin();
|
| + bt_sz != sorted_by_backtrace.end(); bt_sz++) {
|
| + traced_value_->BeginDictionary();
|
| + // Insert a forward reference to the backtrace that will be written to the
|
| + // |stackFrames| dictionary later on.
|
| + traced_value_->SetInteger("bt", sf_deduplicator_->Insert(bt_sz->first));
|
| + WriteSize(bt_sz->second);
|
| + traced_value_->EndDictionary();
|
| + }
|
| +
|
| + traced_value_->EndArray(); // heap
|
| +}
|
| +
|
| +void HeapDumper::WriteSize(size_t size) {
|
| + // Format size as hexadecimal string into |buffer_|.
|
| + SStringPrintf(&buffer_, "%" PRIx64, static_cast<uint64_t>(size));
|
| + traced_value_->SetString("size", buffer_);
|
| +}
|
| +
|
| +} // namespace trace_event
|
| +} // namespace base
|
|
|