1b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Copyright 2015 The Chromium Authors. All rights reserved. 2b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// Use of this source code is governed by a BSD-style license that can be 3b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat// found in the LICENSE file. 4b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 5b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/trace_event_memory_overhead.h" 6b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 7b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include <algorithm> 8b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 90d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko#include "base/bits.h" 10b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/memory/ref_counted_memory.h" 11b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/strings/stringprintf.h" 12b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/memory_allocator_dump.h" 13b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/trace_event/process_memory_dump.h" 14b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat#include "base/values.h" 15b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 16b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace base { 17b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratnamespace trace_event { 18b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 19b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTraceEventMemoryOverhead::TraceEventMemoryOverhead() { 20b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 21b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 22b8cf94937c52feb53b55c39e3f82094d27de464cDaniel EratTraceEventMemoryOverhead::~TraceEventMemoryOverhead() { 23b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 24b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 25b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::AddOrCreateInternal( 26b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const char* object_type, 27b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t count, 28b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t allocated_size_in_bytes, 29b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t resident_size_in_bytes) { 30b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat auto it = allocated_objects_.find(object_type); 31b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (it == allocated_objects_.end()) { 32b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat allocated_objects_.insert(std::make_pair( 33b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat object_type, 34b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ObjectCountAndSize( 35b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat {count, allocated_size_in_bytes, resident_size_in_bytes}))); 36b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat return; 37b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 38b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it->second.count += count; 39b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it->second.allocated_size_in_bytes += allocated_size_in_bytes; 40b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it->second.resident_size_in_bytes += resident_size_in_bytes; 41b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 42b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 43b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::Add(const char* object_type, 44b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t allocated_size_in_bytes) { 45b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add(object_type, allocated_size_in_bytes, allocated_size_in_bytes); 46b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 47b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 48b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::Add(const char* object_type, 49b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t allocated_size_in_bytes, 50b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t resident_size_in_bytes) { 51b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddOrCreateInternal(object_type, 1, allocated_size_in_bytes, 52b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat resident_size_in_bytes); 53b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 54b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 55b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::AddString(const std::string& str) { 56b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // The number below are empirical and mainly based on profiling of real-world 57b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // std::string implementations: 58b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // - even short string end up malloc()-inc at least 32 bytes. 590d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko // - longer strings seem to malloc() multiples of 16 bytes. 600d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const size_t capacity = bits::Align(str.capacity(), 16); 610d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko Add("std::string", sizeof(std::string) + std::max<size_t>(capacity, 32u)); 62b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 63b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 64b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::AddRefCountedString( 65b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const RefCountedString& str) { 66b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add("RefCountedString", sizeof(RefCountedString)); 67b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddString(str.data()); 68b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 69b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 70b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::AddValue(const Value& value) { 71b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat switch (value.GetType()) { 723a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::NONE: 733a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::BOOLEAN: 743a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::INTEGER: 753a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::DOUBLE: 76b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add("FundamentalValue", sizeof(Value)); 77b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat break; 78b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 793a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::STRING: { 803a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli const Value* string_value = nullptr; 81b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value.GetAsString(&string_value); 823a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli Add("StringValue", sizeof(Value)); 83b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddString(string_value->GetString()); 84b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } break; 85b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 863a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::BINARY: { 87b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const BinaryValue* binary_value = nullptr; 88b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value.GetAsBinary(&binary_value); 89b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add("BinaryValue", sizeof(BinaryValue) + binary_value->GetSize()); 90b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } break; 91b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 923a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::DICTIONARY: { 93b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const DictionaryValue* dictionary_value = nullptr; 94b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value.GetAsDictionary(&dictionary_value); 95b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add("DictionaryValue", sizeof(DictionaryValue)); 96b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd(); 97b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it.Advance()) { 98b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddString(it.key()); 99b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddValue(it.value()); 100b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 101b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } break; 102b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1033a83cddbf6d8fe9c9d70d01e008ff8e86a823cb6Jay Civelli case Value::Type::LIST: { 104b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat const ListValue* list_value = nullptr; 105b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat value.GetAsList(&list_value); 106b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add("ListValue", sizeof(ListValue)); 1070c4f26a46430b8c503c65f5cae1d2b6876d53e30Luis Hector Chavez for (const auto& v : *list_value) 108b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddValue(*v); 109b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } break; 110b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 111b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat default: 112b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat NOTREACHED(); 113b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 114b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 115b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 116b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::AddSelf() { 117b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat size_t estimated_size = sizeof(*this); 118b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // If the SmallMap did overflow its static capacity, its elements will be 119b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat // allocated on the heap and have to be accounted separately. 120b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat if (allocated_objects_.UsingFullMap()) 121b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat estimated_size += sizeof(map_type::value_type) * allocated_objects_.size(); 122b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat Add("TraceEventMemoryOverhead", estimated_size); 123b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 124b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 1250d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenkosize_t TraceEventMemoryOverhead::GetCount(const char* object_type) const { 1260d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko const auto& it = allocated_objects_.find(object_type); 1270d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko if (it == allocated_objects_.end()) 1280d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return 0u; 1290d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko return it->second.count; 1300d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko} 1310d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko 132b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead& other) { 133b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& it : other.allocated_objects_) { 134b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat AddOrCreateInternal(it.first, it.second.count, 135b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it.second.allocated_size_in_bytes, 136b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it.second.resident_size_in_bytes); 137b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 138b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 139b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 140b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Eratvoid TraceEventMemoryOverhead::DumpInto(const char* base_name, 141b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat ProcessMemoryDump* pmd) const { 142b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat for (const auto& it : allocated_objects_) { 143b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat std::string dump_name = StringPrintf("%s/%s", base_name, it.first); 144b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MemoryAllocatorDump* mad = pmd->CreateAllocatorDump(dump_name); 145b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat mad->AddScalar(MemoryAllocatorDump::kNameSize, 146b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MemoryAllocatorDump::kUnitsBytes, 147b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it.second.allocated_size_in_bytes); 148b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat mad->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes, 149b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat it.second.resident_size_in_bytes); 1500d205d712abd16eeed2f5d5b1052a367d23a223fAlex Vakulenko mad->AddScalar(MemoryAllocatorDump::kNameObjectCount, 151b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat MemoryAllocatorDump::kUnitsObjects, it.second.count); 152b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat } 153b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} 154b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat 155b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace trace_event 156b8cf94937c52feb53b55c39e3f82094d27de464cDaniel Erat} // namespace base 157