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 #ifndef BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ 6 #define BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ 7 8 #include <stddef.h> 9 10 #include <map> 11 #include <unordered_map> 12 #include <vector> 13 14 #include "base/base_export.h" 15 #include "base/macros.h" 16 #include "base/memory/ref_counted.h" 17 #include "base/trace_event/heap_profiler_allocation_context.h" 18 #include "base/trace_event/memory_allocator_dump.h" 19 #include "base/trace_event/memory_allocator_dump_guid.h" 20 #include "base/trace_event/memory_dump_request_args.h" 21 #include "build/build_config.h" 22 23 // Define COUNT_RESIDENT_BYTES_SUPPORTED if platform supports counting of the 24 // resident memory. 25 #if !defined(OS_NACL) && !defined(OS_BSD) 26 #define COUNT_RESIDENT_BYTES_SUPPORTED 27 #endif 28 29 namespace base { 30 31 class UnguessableToken; 32 33 namespace trace_event { 34 35 class TracedValue; 36 37 // ProcessMemoryDump is as a strongly typed container which holds the dumps 38 // produced by the MemoryDumpProvider(s) for a specific process. 39 class BASE_EXPORT ProcessMemoryDump { 40 public: 41 struct BASE_EXPORT MemoryAllocatorDumpEdge { 42 bool operator==(const MemoryAllocatorDumpEdge&) const; 43 bool operator!=(const MemoryAllocatorDumpEdge&) const; 44 45 MemoryAllocatorDumpGuid source; 46 MemoryAllocatorDumpGuid target; 47 int importance = 0; 48 bool overridable = false; 49 }; 50 51 // Maps allocator dumps absolute names (allocator_name/heap/subheap) to 52 // MemoryAllocatorDump instances. 53 using AllocatorDumpsMap = 54 std::map<std::string, std::unique_ptr<MemoryAllocatorDump>>; 55 56 // Stores allocator dump edges indexed by source allocator dump GUID. 57 using AllocatorDumpEdgesMap = 58 std::map<MemoryAllocatorDumpGuid, MemoryAllocatorDumpEdge>; 59 60 #if defined(COUNT_RESIDENT_BYTES_SUPPORTED) 61 // Returns the number of bytes in a kernel memory page. Some platforms may 62 // have a different value for kernel page sizes from user page sizes. It is 63 // important to use kernel memory page sizes for resident bytes calculation. 64 // In most cases, the two are the same. 65 static size_t GetSystemPageSize(); 66 67 // Returns the total bytes resident for a virtual address range, with given 68 // |start_address| and |mapped_size|. |mapped_size| is specified in bytes. The 69 // value returned is valid only if the given range is currently mmapped by the 70 // process. The |start_address| must be page-aligned. 71 static size_t CountResidentBytes(void* start_address, size_t mapped_size); 72 73 // The same as above, but the given mapped range should belong to the 74 // shared_memory's mapped region. 75 static base::Optional<size_t> CountResidentBytesInSharedMemory( 76 void* start_address, 77 size_t mapped_size); 78 #endif 79 80 explicit ProcessMemoryDump(const MemoryDumpArgs& dump_args); 81 ProcessMemoryDump(ProcessMemoryDump&&); 82 ~ProcessMemoryDump(); 83 84 ProcessMemoryDump& operator=(ProcessMemoryDump&&); 85 86 // Creates a new MemoryAllocatorDump with the given name and returns the 87 // empty object back to the caller. 88 // Arguments: 89 // absolute_name: a name that uniquely identifies allocator dumps produced 90 // by this provider. It is possible to specify nesting by using a 91 // path-like string (e.g., v8/isolate1/heap1, v8/isolate1/heap2). 92 // Leading or trailing slashes are not allowed. 93 // guid: an optional identifier, unique among all processes within the 94 // scope of a global dump. This is only relevant when using 95 // AddOwnershipEdge() to express memory sharing. If omitted, 96 // it will be automatically generated. 97 // ProcessMemoryDump handles the memory ownership of its MemoryAllocatorDumps. 98 MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name); 99 MemoryAllocatorDump* CreateAllocatorDump(const std::string& absolute_name, 100 const MemoryAllocatorDumpGuid& guid); 101 102 // Looks up a MemoryAllocatorDump given its allocator and heap names, or 103 // nullptr if not found. 104 MemoryAllocatorDump* GetAllocatorDump(const std::string& absolute_name) const; 105 106 // Do NOT use this method. All dump providers should use 107 // CreateAllocatorDump(). Tries to create a new MemoryAllocatorDump only if it 108 // doesn't already exist. Creating multiple dumps with same name using 109 // GetOrCreateAllocatorDump() would override the existing scalars in MAD and 110 // cause misreporting. This method is used only in rare cases multiple 111 // components create allocator dumps with same name and only one of them adds 112 // size. 113 MemoryAllocatorDump* GetOrCreateAllocatorDump( 114 const std::string& absolute_name); 115 116 // Creates a shared MemoryAllocatorDump, to express cross-process sharing. 117 // Shared allocator dumps are allowed to have duplicate guids within the 118 // global scope, in order to reference the same dump from multiple processes. 119 // See the design doc goo.gl/keU6Bf for reference usage patterns. 120 MemoryAllocatorDump* CreateSharedGlobalAllocatorDump( 121 const MemoryAllocatorDumpGuid& guid); 122 123 // Creates a shared MemoryAllocatorDump as CreateSharedGlobalAllocatorDump, 124 // but with a WEAK flag. A weak dump will be discarded unless a non-weak dump 125 // is created using CreateSharedGlobalAllocatorDump by at least one process. 126 // The WEAK flag does not apply if a non-weak dump with the same GUID already 127 // exists or is created later. All owners and children of the discarded dump 128 // will also be discarded transitively. 129 MemoryAllocatorDump* CreateWeakSharedGlobalAllocatorDump( 130 const MemoryAllocatorDumpGuid& guid); 131 132 // Looks up a shared MemoryAllocatorDump given its guid. 133 MemoryAllocatorDump* GetSharedGlobalAllocatorDump( 134 const MemoryAllocatorDumpGuid& guid) const; 135 136 // Returns the map of the MemoryAllocatorDumps added to this dump. allocator_dumps()137 const AllocatorDumpsMap& allocator_dumps() const { return allocator_dumps_; } 138 mutable_allocator_dumps_for_serialization()139 AllocatorDumpsMap* mutable_allocator_dumps_for_serialization() const { 140 // Mojo takes a const input argument even for move-only types that can be 141 // mutate while serializing (like this one). Hence the const_cast. 142 return const_cast<AllocatorDumpsMap*>(&allocator_dumps_); 143 } 144 void SetAllocatorDumpsForSerialization( 145 std::vector<std::unique_ptr<MemoryAllocatorDump>>); 146 147 // Only for mojo serialization. 148 std::vector<MemoryAllocatorDumpEdge> GetAllEdgesForSerialization() const; 149 void SetAllEdgesForSerialization(const std::vector<MemoryAllocatorDumpEdge>&); 150 151 // Dumps heap usage with |allocator_name|. 152 void DumpHeapUsage( 153 const std::unordered_map<base::trace_event::AllocationContext, 154 base::trace_event::AllocationMetrics>& 155 metrics_by_context, 156 base::trace_event::TraceEventMemoryOverhead& overhead, 157 const char* allocator_name); 158 159 // Adds an ownership relationship between two MemoryAllocatorDump(s) with the 160 // semantics: |source| owns |target|, and has the effect of attributing 161 // the memory usage of |target| to |source|. |importance| is optional and 162 // relevant only for the cases of co-ownership, where it acts as a z-index: 163 // the owner with the highest importance will be attributed |target|'s memory. 164 // If an edge is present, its importance will not be updated unless 165 // |importance| is larger. 166 void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, 167 const MemoryAllocatorDumpGuid& target, 168 int importance); 169 void AddOwnershipEdge(const MemoryAllocatorDumpGuid& source, 170 const MemoryAllocatorDumpGuid& target); 171 172 // Adds edges that can be overriden by a later or earlier call to 173 // AddOwnershipEdge() with the same source and target with a different 174 // |importance| value. 175 void AddOverridableOwnershipEdge(const MemoryAllocatorDumpGuid& source, 176 const MemoryAllocatorDumpGuid& target, 177 int importance); 178 179 // Creates ownership edges for shared memory. Handles the case of cross 180 // process sharing and importance of ownership for the case with and without 181 // the shared memory dump provider. This handles both shared memory from both 182 // legacy base::SharedMemory as well as current base::SharedMemoryMapping. The 183 // weak version creates a weak global dump. 184 // |client_local_dump_guid| The guid of the local dump created by the client 185 // of base::SharedMemory. 186 // |shared_memory_guid| The ID of the shared memory that is assigned globally, 187 // used to create global dump edges in the new model. 188 // |importance| Importance of the global dump edges to say if the current 189 // process owns the memory segment. 190 void CreateSharedMemoryOwnershipEdge( 191 const MemoryAllocatorDumpGuid& client_local_dump_guid, 192 const UnguessableToken& shared_memory_guid, 193 int importance); 194 void CreateWeakSharedMemoryOwnershipEdge( 195 const MemoryAllocatorDumpGuid& client_local_dump_guid, 196 const UnguessableToken& shared_memory_guid, 197 int importance); 198 allocator_dumps_edges()199 const AllocatorDumpEdgesMap& allocator_dumps_edges() const { 200 return allocator_dumps_edges_; 201 } 202 203 // Utility method to add a suballocation relationship with the following 204 // semantics: |source| is suballocated from |target_node_name|. 205 // This creates a child node of |target_node_name| and adds an ownership edge 206 // between |source| and the new child node. As a result, the UI will not 207 // account the memory of |source| in the target node. 208 void AddSuballocation(const MemoryAllocatorDumpGuid& source, 209 const std::string& target_node_name); 210 211 // Removes all the MemoryAllocatorDump(s) contained in this instance. This 212 // ProcessMemoryDump can be safely reused as if it was new once this returns. 213 void Clear(); 214 215 // Merges all MemoryAllocatorDump(s) contained in |other| inside this 216 // ProcessMemoryDump, transferring their ownership to this instance. 217 // |other| will be an empty ProcessMemoryDump after this method returns. 218 // This is to allow dump providers to pre-populate ProcessMemoryDump instances 219 // and later move their contents into the ProcessMemoryDump passed as argument 220 // of the MemoryDumpProvider::OnMemoryDump(ProcessMemoryDump*) callback. 221 void TakeAllDumpsFrom(ProcessMemoryDump* other); 222 223 // Populate the traced value with information about the memory allocator 224 // dumps. 225 void SerializeAllocatorDumpsInto(TracedValue* value) const; 226 dump_args()227 const MemoryDumpArgs& dump_args() const { return dump_args_; } 228 229 private: 230 FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, BackgroundModeTest); 231 FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, SharedMemoryOwnershipTest); 232 FRIEND_TEST_ALL_PREFIXES(ProcessMemoryDumpTest, GuidsTest); 233 234 MemoryAllocatorDump* AddAllocatorDumpInternal( 235 std::unique_ptr<MemoryAllocatorDump> mad); 236 237 // A per-process token, valid throughout all the lifetime of the current 238 // process, used to disambiguate dumps with the same name generated in 239 // different processes. process_token()240 const UnguessableToken& process_token() const { return process_token_; } set_process_token_for_testing(UnguessableToken token)241 void set_process_token_for_testing(UnguessableToken token) { 242 process_token_ = token; 243 } 244 245 // Returns the Guid of the dump for the given |absolute_name| for 246 // for the given process' token. |process_token| is used to disambiguate GUIDs 247 // derived from the same name under different processes. 248 MemoryAllocatorDumpGuid GetDumpId(const std::string& absolute_name); 249 250 void CreateSharedMemoryOwnershipEdgeInternal( 251 const MemoryAllocatorDumpGuid& client_local_dump_guid, 252 const UnguessableToken& shared_memory_guid, 253 int importance, 254 bool is_weak); 255 256 MemoryAllocatorDump* GetBlackHoleMad(); 257 258 UnguessableToken process_token_; 259 AllocatorDumpsMap allocator_dumps_; 260 261 // Keeps track of relationships between MemoryAllocatorDump(s). 262 AllocatorDumpEdgesMap allocator_dumps_edges_; 263 264 // Level of detail of the current dump. 265 MemoryDumpArgs dump_args_; 266 267 // This allocator dump is returned when an invalid dump is created in 268 // background mode. The attributes of the dump are ignored and not added to 269 // the trace. 270 std::unique_ptr<MemoryAllocatorDump> black_hole_mad_; 271 272 // When set to true, the DCHECK(s) for invalid dump creations on the 273 // background mode are disabled for testing. 274 static bool is_black_hole_non_fatal_for_testing_; 275 276 DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump); 277 }; 278 279 } // namespace trace_event 280 } // namespace base 281 282 #endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ 283