| // 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/trace_event_memory_overhead.h" |
| |
| #include <algorithm> |
| |
| #include "base/bits.h" |
| #include "base/memory/ref_counted_memory.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/trace_event/memory_allocator_dump.h" |
| #include "base/trace_event/memory_usage_estimator.h" |
| #include "base/trace_event/process_memory_dump.h" |
| #include "base/values.h" |
| |
| namespace base { |
| namespace trace_event { |
| |
| namespace { |
| |
| const char* ObjectTypeToString(TraceEventMemoryOverhead::ObjectType type) { |
| switch (type) { |
| case TraceEventMemoryOverhead::kOther: |
| return "(Other)"; |
| case TraceEventMemoryOverhead::kTraceBuffer: |
| return "TraceBuffer"; |
| case TraceEventMemoryOverhead::kTraceBufferChunk: |
| return "TraceBufferChunk"; |
| case TraceEventMemoryOverhead::kTraceEvent: |
| return "TraceEvent"; |
| case TraceEventMemoryOverhead::kUnusedTraceEvent: |
| return "TraceEvent(Unused)"; |
| case TraceEventMemoryOverhead::kTracedValue: |
| return "TracedValue"; |
| case TraceEventMemoryOverhead::kConvertableToTraceFormat: |
| return "ConvertableToTraceFormat"; |
| case TraceEventMemoryOverhead::kHeapProfilerAllocationRegister: |
| return "AllocationRegister"; |
| case TraceEventMemoryOverhead::kHeapProfilerTypeNameDeduplicator: |
| return "TypeNameDeduplicator"; |
| case TraceEventMemoryOverhead::kHeapProfilerStackFrameDeduplicator: |
| return "StackFrameDeduplicator"; |
| case TraceEventMemoryOverhead::kStdString: |
| return "std::string"; |
| case TraceEventMemoryOverhead::kBaseValue: |
| return "base::Value"; |
| case TraceEventMemoryOverhead::kTraceEventMemoryOverhead: |
| return "TraceEventMemoryOverhead"; |
| case TraceEventMemoryOverhead::kFrameMetrics: |
| return "FrameMetrics"; |
| case TraceEventMemoryOverhead::kLast: |
| NOTREACHED(); |
| } |
| NOTREACHED(); |
| return "BUG"; |
| } |
| |
| } // namespace |
| |
| TraceEventMemoryOverhead::TraceEventMemoryOverhead() : allocated_objects_() {} |
| |
| TraceEventMemoryOverhead::~TraceEventMemoryOverhead() = default; |
| |
| void TraceEventMemoryOverhead::AddInternal(ObjectType object_type, |
| size_t count, |
| size_t allocated_size_in_bytes, |
| size_t resident_size_in_bytes) { |
| ObjectCountAndSize& count_and_size = |
| allocated_objects_[static_cast<uint32_t>(object_type)]; |
| count_and_size.count += count; |
| count_and_size.allocated_size_in_bytes += allocated_size_in_bytes; |
| count_and_size.resident_size_in_bytes += resident_size_in_bytes; |
| } |
| |
| void TraceEventMemoryOverhead::Add(ObjectType object_type, |
| size_t allocated_size_in_bytes) { |
| Add(object_type, allocated_size_in_bytes, allocated_size_in_bytes); |
| } |
| |
| void TraceEventMemoryOverhead::Add(ObjectType object_type, |
| size_t allocated_size_in_bytes, |
| size_t resident_size_in_bytes) { |
| AddInternal(object_type, 1, allocated_size_in_bytes, resident_size_in_bytes); |
| } |
| |
| void TraceEventMemoryOverhead::AddString(const std::string& str) { |
| Add(kStdString, EstimateMemoryUsage(str)); |
| } |
| |
| void TraceEventMemoryOverhead::AddRefCountedString( |
| const RefCountedString& str) { |
| Add(kOther, sizeof(RefCountedString)); |
| AddString(str.data()); |
| } |
| |
| void TraceEventMemoryOverhead::AddValue(const Value& value) { |
| switch (value.type()) { |
| case Value::Type::NONE: |
| case Value::Type::BOOLEAN: |
| case Value::Type::INTEGER: |
| case Value::Type::DOUBLE: |
| Add(kBaseValue, sizeof(Value)); |
| break; |
| |
| case Value::Type::STRING: { |
| const Value* string_value = nullptr; |
| value.GetAsString(&string_value); |
| Add(kBaseValue, sizeof(Value)); |
| AddString(string_value->GetString()); |
| } break; |
| |
| case Value::Type::BINARY: { |
| Add(kBaseValue, sizeof(Value) + value.GetBlob().size()); |
| } break; |
| |
| case Value::Type::DICTIONARY: { |
| const DictionaryValue* dictionary_value = nullptr; |
| value.GetAsDictionary(&dictionary_value); |
| Add(kBaseValue, sizeof(DictionaryValue)); |
| for (DictionaryValue::Iterator it(*dictionary_value); !it.IsAtEnd(); |
| it.Advance()) { |
| AddString(it.key()); |
| AddValue(it.value()); |
| } |
| } break; |
| |
| case Value::Type::LIST: { |
| const ListValue* list_value = nullptr; |
| value.GetAsList(&list_value); |
| Add(kBaseValue, sizeof(ListValue)); |
| for (const auto& v : *list_value) |
| AddValue(v); |
| } break; |
| |
| default: |
| NOTREACHED(); |
| } |
| } |
| |
| void TraceEventMemoryOverhead::AddSelf() { |
| Add(kTraceEventMemoryOverhead, sizeof(*this)); |
| } |
| |
| size_t TraceEventMemoryOverhead::GetCount(ObjectType object_type) const { |
| CHECK(object_type < kLast); |
| return allocated_objects_[static_cast<uint32_t>(object_type)].count; |
| } |
| |
| void TraceEventMemoryOverhead::Update(const TraceEventMemoryOverhead& other) { |
| for (uint32_t i = 0; i < kLast; i++) { |
| const ObjectCountAndSize& other_entry = other.allocated_objects_[i]; |
| AddInternal(static_cast<ObjectType>(i), other_entry.count, |
| other_entry.allocated_size_in_bytes, |
| other_entry.resident_size_in_bytes); |
| } |
| } |
| |
| #if !defined(STARBOARD) |
| void TraceEventMemoryOverhead::DumpInto(const char* base_name, |
| ProcessMemoryDump* pmd) const { |
| for (uint32_t i = 0; i < kLast; i++) { |
| const ObjectCountAndSize& count_and_size = allocated_objects_[i]; |
| if (count_and_size.allocated_size_in_bytes == 0) |
| continue; |
| std::string dump_name = StringPrintf( |
| "%s/%s", base_name, ObjectTypeToString(static_cast<ObjectType>(i))); |
| MemoryAllocatorDump* mad = pmd->CreateAllocatorDump(dump_name); |
| mad->AddScalar(MemoryAllocatorDump::kNameSize, |
| MemoryAllocatorDump::kUnitsBytes, |
| count_and_size.allocated_size_in_bytes); |
| mad->AddScalar("resident_size", MemoryAllocatorDump::kUnitsBytes, |
| count_and_size.resident_size_in_bytes); |
| mad->AddScalar(MemoryAllocatorDump::kNameObjectCount, |
| MemoryAllocatorDump::kUnitsObjects, count_and_size.count); |
| } |
| } |
| #endif |
| |
| } // namespace trace_event |
| } // namespace base |