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 3 // found in the LICENSE file. 4 5 #include "base/trace_event/memory_allocator_dump.h" 6 7 #include "base/format_macros.h" 8 #include "base/strings/stringprintf.h" 9 #include "base/trace_event/memory_dump_manager.h" 10 #include "base/trace_event/memory_dump_provider.h" 11 #include "base/trace_event/process_memory_dump.h" 12 #include "base/trace_event/trace_event_argument.h" 13 #include "base/values.h" 14 15 namespace base { 16 namespace trace_event { 17 18 const char MemoryAllocatorDump::kNameSize[] = "size"; 19 const char MemoryAllocatorDump::kNameObjectCount[] = "object_count"; 20 const char MemoryAllocatorDump::kTypeScalar[] = "scalar"; 21 const char MemoryAllocatorDump::kTypeString[] = "string"; 22 const char MemoryAllocatorDump::kUnitsBytes[] = "bytes"; 23 const char MemoryAllocatorDump::kUnitsObjects[] = "objects"; 24 25 MemoryAllocatorDump::MemoryAllocatorDump(const std::string& absolute_name, 26 ProcessMemoryDump* process_memory_dump, 27 const MemoryAllocatorDumpGuid& guid) 28 : absolute_name_(absolute_name), 29 process_memory_dump_(process_memory_dump), 30 attributes_(new TracedValue), 31 guid_(guid), 32 flags_(Flags::DEFAULT) { 33 // The |absolute_name| cannot be empty. 34 DCHECK(!absolute_name.empty()); 35 36 // The |absolute_name| can contain slash separator, but not leading or 37 // trailing ones. 38 DCHECK(absolute_name[0] != '/' && *absolute_name.rbegin() != '/'); 39 } 40 41 // If the caller didn't provide a guid, make one up by hashing the 42 // absolute_name with the current PID. 43 // Rationale: |absolute_name| is already supposed to be unique within a 44 // process, the pid will make it unique among all processes. 45 MemoryAllocatorDump::MemoryAllocatorDump(const std::string& absolute_name, 46 ProcessMemoryDump* process_memory_dump) 47 : MemoryAllocatorDump(absolute_name, 48 process_memory_dump, 49 MemoryAllocatorDumpGuid(StringPrintf( 50 "%d:%s", 51 TraceLog::GetInstance()->process_id(), 52 absolute_name.c_str()))) { 53 string_conversion_buffer_.reserve(16); 54 } 55 56 MemoryAllocatorDump::~MemoryAllocatorDump() { 57 } 58 59 void MemoryAllocatorDump::AddScalar(const char* name, 60 const char* units, 61 uint64_t value) { 62 SStringPrintf(&string_conversion_buffer_, "%" PRIx64, value); 63 attributes_->BeginDictionary(name); 64 attributes_->SetString("type", kTypeScalar); 65 attributes_->SetString("units", units); 66 attributes_->SetString("value", string_conversion_buffer_); 67 attributes_->EndDictionary(); 68 } 69 70 void MemoryAllocatorDump::AddScalarF(const char* name, 71 const char* units, 72 double value) { 73 attributes_->BeginDictionary(name); 74 attributes_->SetString("type", kTypeScalar); 75 attributes_->SetString("units", units); 76 attributes_->SetDouble("value", value); 77 attributes_->EndDictionary(); 78 } 79 80 void MemoryAllocatorDump::AddString(const char* name, 81 const char* units, 82 const std::string& value) { 83 // String attributes are disabled in background mode. 84 if (process_memory_dump_->dump_args().level_of_detail == 85 MemoryDumpLevelOfDetail::BACKGROUND) { 86 NOTREACHED(); 87 return; 88 } 89 90 attributes_->BeginDictionary(name); 91 attributes_->SetString("type", kTypeString); 92 attributes_->SetString("units", units); 93 attributes_->SetString("value", value); 94 attributes_->EndDictionary(); 95 } 96 97 void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { 98 value->BeginDictionaryWithCopiedName(absolute_name_); 99 value->SetString("guid", guid_.ToString()); 100 value->SetValue("attrs", *attributes_); 101 if (flags_) 102 value->SetInteger("flags", flags_); 103 value->EndDictionary(); // "allocator_name/heap_subheap": { ... } 104 } 105 106 } // namespace trace_event 107 } // namespace base 108