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 size_(0) { 34 // The |absolute_name| cannot be empty. 35 DCHECK(!absolute_name.empty()); 36 37 // The |absolute_name| can contain slash separator, but not leading or 38 // trailing ones. 39 DCHECK(absolute_name[0] != '/' && *absolute_name.rbegin() != '/'); 40 } 41 42 // If the caller didn't provide a guid, make one up by hashing the 43 // absolute_name with the current PID. 44 // Rationale: |absolute_name| is already supposed to be unique within a 45 // process, the pid will make it unique among all processes. 46 MemoryAllocatorDump::MemoryAllocatorDump(const std::string& absolute_name, 47 ProcessMemoryDump* process_memory_dump) 48 : MemoryAllocatorDump(absolute_name, 49 process_memory_dump, 50 MemoryAllocatorDumpGuid(StringPrintf( 51 "%d:%s", 52 TraceLog::GetInstance()->process_id(), 53 absolute_name.c_str()))) { 54 string_conversion_buffer_.reserve(16); 55 } 56 57 MemoryAllocatorDump::~MemoryAllocatorDump() { 58 } 59 60 void MemoryAllocatorDump::AddScalar(const char* name, 61 const char* units, 62 uint64_t value) { 63 if (strcmp(kNameSize, name) == 0) 64 size_ = value; 65 SStringPrintf(&string_conversion_buffer_, "%" PRIx64, value); 66 attributes_->BeginDictionary(name); 67 attributes_->SetString("type", kTypeScalar); 68 attributes_->SetString("units", units); 69 attributes_->SetString("value", string_conversion_buffer_); 70 attributes_->EndDictionary(); 71 } 72 73 void MemoryAllocatorDump::AddScalarF(const char* name, 74 const char* units, 75 double value) { 76 attributes_->BeginDictionary(name); 77 attributes_->SetString("type", kTypeScalar); 78 attributes_->SetString("units", units); 79 attributes_->SetDouble("value", value); 80 attributes_->EndDictionary(); 81 } 82 83 void MemoryAllocatorDump::AddString(const char* name, 84 const char* units, 85 const std::string& value) { 86 // String attributes are disabled in background mode. 87 if (process_memory_dump_->dump_args().level_of_detail == 88 MemoryDumpLevelOfDetail::BACKGROUND) { 89 NOTREACHED(); 90 return; 91 } 92 93 attributes_->BeginDictionary(name); 94 attributes_->SetString("type", kTypeString); 95 attributes_->SetString("units", units); 96 attributes_->SetString("value", value); 97 attributes_->EndDictionary(); 98 } 99 100 void MemoryAllocatorDump::AsValueInto(TracedValue* value) const { 101 value->BeginDictionaryWithCopiedName(absolute_name_); 102 value->SetString("guid", guid_.ToString()); 103 value->SetValue("attrs", *attributes_); 104 if (flags_) 105 value->SetInteger("flags", flags_); 106 value->EndDictionary(); // "allocator_name/heap_subheap": { ... } 107 } 108 109 } // namespace trace_event 110 } // namespace base 111