1 // Copyright 2015 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ 6 #define BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ 7 8 #include <stdint.h> 9 10 #include <iosfwd> 11 #include <memory> 12 #include <optional> 13 #include <string> 14 #include <string_view> 15 #include <vector> 16 17 #include "base/base_export.h" 18 #include "base/compiler_specific.h" 19 #include "base/trace_event/memory_allocator_dump_guid.h" 20 #include "base/trace_event/memory_dump_request_args.h" 21 #include "base/unguessable_token.h" 22 23 namespace perfetto { 24 namespace protos { 25 namespace pbzero { 26 class MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode; 27 } 28 } // namespace protos 29 } // namespace perfetto 30 31 namespace base { 32 namespace trace_event { 33 34 class ProcessMemoryDump; 35 class TracedValue; 36 37 // Data model for user-land memory allocator dumps. 38 class BASE_EXPORT MemoryAllocatorDump { 39 public: 40 enum Flags { 41 kDefault = 0, 42 43 // A dump marked weak will be discarded by TraceViewer. 44 kWeak = 1 << 0, 45 }; 46 47 // In the TraceViewer UI table each MemoryAllocatorDump becomes 48 // a row and each Entry generates a column (if it doesn't already 49 // exist). 50 struct BASE_EXPORT Entry { 51 enum EntryType { 52 kUint64, 53 kString, 54 }; 55 56 // By design name, units and value_string are always coming from 57 // indefinitely lived const char* strings, the only reason we copy 58 // them into a std::string is to handle Mojo (de)serialization. 59 // TODO(hjd): Investigate optimization (e.g. using std::string_view). 60 Entry(); // Only for deserialization. 61 Entry(std::string name, std::string units, uint64_t value); 62 Entry(std::string name, std::string units, std::string value); 63 Entry(Entry&& other) noexcept; 64 Entry(const Entry&) = delete; 65 Entry& operator=(const Entry&) = delete; 66 Entry& operator=(Entry&& other); 67 bool operator==(const Entry& rhs) const; 68 69 std::string name; 70 std::string units; 71 72 EntryType entry_type; 73 74 uint64_t value_uint64; 75 std::string value_string; 76 }; 77 78 MemoryAllocatorDump(const std::string& absolute_name, 79 MemoryDumpLevelOfDetail, 80 const MemoryAllocatorDumpGuid&); 81 MemoryAllocatorDump(const MemoryAllocatorDump&) = delete; 82 MemoryAllocatorDump& operator=(const MemoryAllocatorDump&) = delete; 83 ~MemoryAllocatorDump(); 84 85 // Standard attribute |name|s for the AddScalar and AddString() methods. 86 static const char kNameSize[]; // To represent allocated space. 87 static const char kNameObjectCount[]; // To represent number of objects. 88 89 // Standard attribute |unit|s for the AddScalar and AddString() methods. 90 static const char kUnitsBytes[]; // Unit name to represent bytes. 91 static const char kUnitsObjects[]; // Unit name to represent #objects. 92 93 // Constants used only internally and by tests. 94 static const char kTypeScalar[]; // Type name for scalar attributes. 95 static const char kTypeString[]; // Type name for string attributes. 96 97 // Setters for scalar attributes. Some examples: 98 // - "size" column (all dumps are expected to have at least this one): 99 // AddScalar(kNameSize, kUnitsBytes, 1234); 100 // - Some extra-column reporting internal details of the subsystem: 101 // AddScalar("number_of_freelist_entries", kUnitsObjects, 42) 102 // - Other informational column: 103 // AddString("kitten", "name", "shadow"); 104 void AddScalar(const char* name, const char* units, uint64_t value); 105 void AddString(const char* name, const char* units, const std::string& value); 106 107 // Absolute name, unique within the scope of an entire ProcessMemoryDump. absolute_name()108 const std::string& absolute_name() const LIFETIME_BOUND { 109 return absolute_name_; 110 } 111 112 // Called at trace generation time to populate the TracedValue. 113 void AsValueInto(TracedValue* value) const; 114 115 void AsProtoInto( 116 perfetto::protos::pbzero:: 117 MemoryTrackerSnapshot_ProcessSnapshot_MemoryNode* memory_node) const; 118 119 // Get the size for this dump. 120 // The size is the value set with AddScalar(kNameSize, kUnitsBytes, size); 121 // TODO(hjd): this should return an optional<uint64_t>. 122 uint64_t GetSizeInternal() const; 123 level_of_detail()124 MemoryDumpLevelOfDetail level_of_detail() const { return level_of_detail_; } 125 126 // Use enum Flags to set values. set_flags(int flags)127 void set_flags(int flags) { flags_ |= flags; } clear_flags(int flags)128 void clear_flags(int flags) { flags_ &= ~flags; } flags()129 int flags() const { return flags_; } 130 131 // |guid| is an optional global dump identifier, unique across all processes 132 // within the scope of a global dump. It is only required when using the 133 // graph APIs (see TODO_method_name) to express retention / suballocation or 134 // cross process sharing. See crbug.com/492102 for design docs. 135 // Subsequent MemoryAllocatorDump(s) with the same |absolute_name| are 136 // expected to have the same guid. guid()137 const MemoryAllocatorDumpGuid& guid() const LIFETIME_BOUND { return guid_; } 138 entries()139 const std::vector<Entry>& entries() const LIFETIME_BOUND { return entries_; } 140 141 // Only for mojo serialization, which can mutate the collection. mutable_entries_for_serialization()142 std::vector<Entry>* mutable_entries_for_serialization() const { 143 cached_size_.reset(); // The caller can mutate the collection. 144 145 // Mojo takes a const input argument even for move-only types that can be 146 // mutate while serializing (like this one). Hence the const_cast. 147 return const_cast<std::vector<Entry>*>(&entries_); 148 } 149 150 private: 151 const std::string absolute_name_; 152 MemoryAllocatorDumpGuid guid_; 153 MemoryDumpLevelOfDetail level_of_detail_; 154 int flags_; // See enum Flags. 155 mutable std::optional<uint64_t> cached_size_; // Lazy, for GetSizeInternal(). 156 std::vector<Entry> entries_; 157 }; 158 159 // This is required by gtest to print a readable output on test failures. 160 void BASE_EXPORT PrintTo(const MemoryAllocatorDump::Entry&, std::ostream*); 161 162 } // namespace trace_event 163 } // namespace base 164 165 #endif // BASE_TRACE_EVENT_MEMORY_ALLOCATOR_DUMP_H_ 166