diff options
Diffstat (limited to 'base/trace_event/process_memory_dump.h')
-rw-r--r-- | base/trace_event/process_memory_dump.h | 284 |
1 files changed, 284 insertions, 0 deletions
diff --git a/base/trace_event/process_memory_dump.h b/base/trace_event/process_memory_dump.h new file mode 100644 index 0000000000..e2457b7389 --- /dev/null +++ b/base/trace_event/process_memory_dump.h @@ -0,0 +1,284 @@ +// Copyright 2015 The Chromium Authors. All rights reserved. +// 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 <unordered_map> +#include <vector> + +#include "base/base_export.h" +#include "base/macros.h" +#include "base/memory/ref_counted.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 !defined(OS_NACL) +#define COUNT_RESIDENT_BYTES_SUPPORTED +#endif + +namespace base { + +class SharedMemory; +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 { + bool operator==(const MemoryAllocatorDumpEdge&) const; + bool operator!=(const MemoryAllocatorDumpEdge&) const; + + 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 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 base::Optional<size_t> CountResidentBytesInSharedMemory( + void* start_address, + size_t mapped_size); +#endif + + explicit ProcessMemoryDump(const MemoryDumpArgs& dump_args); + ProcessMemoryDump(ProcessMemoryDump&&); + ~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 { 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>&); + + // Dumps heap usage with |allocator_name|. + void DumpHeapUsage( + const std::unordered_map<base::trace_event::AllocationContext, + base::trace_event::AllocationMetrics>& + metrics_by_context, + base::trace_event::TraceEventMemoryOverhead& overhead, + const char* allocator_name); + + // 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 memory backed by base::SharedMemory. Handles + // the case of cross process sharing and importnace of ownership for the case + // with and without the base::SharedMemory dump provider. The new version + // should just use global dumps created by SharedMemoryTracker and this + // function handles the transition until we get SharedMemory IDs through mojo + // channel crbug.com/713763. 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 base::SharedMemory 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 { + 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; + + const MemoryDumpArgs& dump_args() const { 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 { 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(); + + 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_; + + DISALLOW_COPY_AND_ASSIGN(ProcessMemoryDump); +}; + +} // namespace trace_event +} // namespace base + +#endif // BASE_TRACE_EVENT_PROCESS_MEMORY_DUMP_H_ |