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