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