| # Adding MemoryInfra Tracing to a Component | 
 |  | 
 | If you have a component that manages memory allocations, you should be | 
 | registering and tracking those allocations with Chrome's MemoryInfra system. | 
 | This lets you: | 
 |  | 
 |  * See an overview of your allocations, giving insight into total size and | 
 |    breakdown. | 
 |  * Understand how your allocations change over time and how they are impacted by | 
 |    other parts of Chrome. | 
 |  * Catch regressions in your component's allocations size by setting up | 
 |    telemetry tests which monitor your allocation sizes under certain | 
 |    circumstances. | 
 |  | 
 | Some existing components that use MemoryInfra: | 
 |  | 
 |  * **Discardable Memory**: Tracks usage of discardable memory throughout Chrome. | 
 |  * **GPU**: Tracks OpenGL and other GPU object allocations. | 
 |  * **V8**: Tracks the heap size for JS. | 
 |  | 
 | [TOC] | 
 |  | 
 | ## Overview | 
 |  | 
 | In order to hook into Chrome's MemoryInfra system, your component needs to do | 
 | two things: | 
 |  | 
 |  1. Create a [`MemoryDumpProvider`][mdp] for your component. | 
 |  2. Register and unregister you dump provider with the | 
 |     [`MemoryDumpManager`][mdm]. | 
 |  | 
 | [mdp]: https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/memory_dump_provider.h | 
 | [mdm]: https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/memory_dump_manager.h | 
 |  | 
 | ## Creating a Memory Dump Provider | 
 |  | 
 | You can implement a [`MemoryDumpProvider`][mdp] as a stand-alone class, or as an | 
 | additional interface on an existing class. For example, this interface is | 
 | frequently implemented on classes which manage a pool of allocations (see | 
 | [`cc::ResourcePool`][resource-pool] for an example). | 
 |  | 
 | A `MemoryDumpProvider` has one basic job, to implement `OnMemoryDump`. This | 
 | function is responsible for iterating over the resources allocated or tracked by | 
 | your component, and creating a [`MemoryAllocatorDump`][mem-alloc-dump] for each | 
 | using [`ProcessMemoryDump::CreateAllocatorDump`][pmd]. A simple example: | 
 |  | 
 | ```cpp | 
 | bool MyComponent::OnMemoryDump(const MemoryDumpArgs& args, | 
 |                                ProcessMemoryDump* process_memory_dump) { | 
 |   for (const auto& allocation : my_allocations_) { | 
 |     auto* dump = process_memory_dump->CreateAllocatorDump( | 
 |         "path/to/my/component/allocation_" + allocation.id().ToString()); | 
 |     dump->AddScalar(base::trace_event::MemoryAllocatorDump::kNameSize, | 
 |                     base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 
 |                     allocation.size_bytes()); | 
 |  | 
 |     // While you will typically have a kNameSize entry, you can add additional | 
 |     // entries to your dump with free-form names. In this example we also dump | 
 |     // an object's "free_size", assuming the object may not be entirely in use. | 
 |     dump->AddScalar("free_size", | 
 |                     base::trace_event::MemoryAllocatorDump::kUnitsBytes, | 
 |                     allocation.free_size_bytes()); | 
 |   } | 
 | } | 
 | ``` | 
 |  | 
 | For many components, this may be all that is needed. See | 
 | [Handling Shared Memory Allocations](#Handling-Shared-Memory-Allocations) and | 
 | [Suballocations](#Suballocations) for information on more complex use cases. | 
 |  | 
 | [resource-pool]:  https://chromium.googlesource.com/chromium/src/+/master/cc/resources/resource_pool.h | 
 | [mem-alloc-dump]: https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/memory_allocator_dump.h | 
 | [pmd]:            https://chromium.googlesource.com/chromium/src/+/master/base/trace_event/process_memory_dump.h | 
 |  | 
 | ## Registering a Memory Dump Provider | 
 |  | 
 | Once you have created a [`MemoryDumpProvider`][mdp], you need to register it | 
 | with the [`MemoryDumpManager`][mdm] before the system can start polling it for | 
 | memory information. Registration is generally straightforward, and involves | 
 | calling `MemoryDumpManager::RegisterDumpProvider`: | 
 |  | 
 | ```cpp | 
 | // Each process uses a singleton |MemoryDumpManager|. | 
 | base::trace_event::MemoryDumpManager::GetInstance()->RegisterDumpProvider( | 
 |     my_memory_dump_provider_, my_single_thread_task_runner_); | 
 | ``` | 
 |  | 
 | In the above code, `my_memory_dump_provider_` is the `MemoryDumpProvider` | 
 | outlined in the previous section. `my_single_thread_task_runner_` is more | 
 | complex and may be a number of things: | 
 |  | 
 |  * Most commonly, if your component is always used from the main message loop, | 
 |    `my_single_thread_task_runner_` may just be | 
 |    [`base::ThreadTaskRunnerHandle::Get()`][task-runner-handle]. | 
 |  * If your component already uses a custom `base::SingleThreadTaskRunner` for | 
 |    executing tasks on a specific thread, you should likely use this runner. | 
 |  | 
 | [task-runner-handle]: https://chromium.googlesource.com/chromium/src/+/master/base/thread_task_runner_handle.h | 
 |  | 
 | ## Unregistration | 
 |  | 
 | Unregistration must happen on the thread belonging to the | 
 | `SingleThreadTaskRunner` provided at registration time. Unregistering on another | 
 | thread can lead to race conditions if tracing is active when the provider is | 
 | unregistered. | 
 |  | 
 | ```cpp | 
 | base::trace_event::MemoryDumpManager::GetInstance()->UnregisterDumpProvider( | 
 |       my_memory_dump_provider_); | 
 | ``` | 
 |  | 
 | ## Handling Shared Memory Allocations | 
 |  | 
 | When an allocation is shared between two components, it may be useful to dump | 
 | the allocation in both components, but you also want to avoid double-counting | 
 | the allocation. This can be achieved using the concept of _ownership edges_. | 
 | An ownership edge represents that the _source_ memory allocator dump owns a | 
 | _target_ memory allocator dump. If multiple source dumps own a single target, | 
 | then the cost of that target allocation will be split between the sources. | 
 | Additionally, importance can be added to a specific ownership edge, allowing | 
 | the highest importance source of that edge to claim the entire cost of the | 
 | target. | 
 |  | 
 | In the typical case, you will use [`ProcessMemoryDump`][pmd] to create a shared | 
 | global allocator dump. This dump will act as the target of all | 
 | component-specific dumps of a specific resource: | 
 |  | 
 | ```cpp | 
 | // Component 1 is going to create a dump, source_mad, for an allocation, | 
 | // alloc_, which may be shared with other components / processes. | 
 | MyAllocationType* alloc_; | 
 | base::trace_event::MemoryAllocatorDump* source_mad; | 
 |  | 
 | // Component 1 creates and populates source_mad; | 
 | ... | 
 |  | 
 | // In addition to creating a source dump, we must create a global shared | 
 | // target dump. This dump should be created with a unique global ID which can be | 
 | // generated any place the allocation is used. I recommend adding a global ID | 
 | // generation function to the allocation type. | 
 | base::trace_event::MemoryAllocatorDumpGUID guid(alloc_->GetGUIDString()); | 
 |  | 
 | // From this global ID we can generate the parent allocator dump. | 
 | base::trace_event::MemoryAllocatorDump* target_mad = | 
 |     process_memory_dump->CreateSharedGlobalAllocatorDump(guid); | 
 |  | 
 | // We now create an ownership edge from the source dump to the target dump. | 
 | // When creating an edge, you can assign an importance to this edge. If all | 
 | // edges have the same importance, the size of the allocation will be split | 
 | // between all sources which create a dump for the allocation. If one | 
 | // edge has higher importance than the others, its source will be assigned the | 
 | // full size of the allocation. | 
 | const int kImportance = 1; | 
 | process_memory_dump->AddOwnershipEdge( | 
 |     source_mad->guid(), target_mad->guid(), kImportance); | 
 | ``` | 
 |  | 
 | If an allocation is being shared across process boundaries, it may be useful to | 
 | generate a global ID which incorporates the ID of the local process, preventing | 
 | two processes from generating colliding IDs. As it is not recommended to pass a | 
 | process ID between processes for security reasons, a function | 
 | `MemoryDumpManager::GetTracingProcessId` is provided which generates a unique ID | 
 | per process that can be passed with the resource without security concerns. | 
 | Frequently this ID is used to generate a global ID that is based on the | 
 | allocated resource's ID combined with the allocating process' tracing ID. | 
 |  | 
 | ## Suballocations | 
 |  | 
 | Another advanced use case involves tracking sub-allocations of a larger | 
 | allocation. For instance, this is used in | 
 | [`gpu::gles2::TextureManager`][texture-manager] to dump both the suballocations | 
 | which make up a texture. To create a suballocation, instead of calling | 
 | [`ProcessMemoryDump::CreateAllocatorDump`][pmd] to create a | 
 | [`MemoryAllocatorDump`][mem-alloc-dump], you call | 
 | [`ProcessMemoryDump::AddSubAllocation`][pmd], providing the ID of the parent | 
 | allocation as the first parameter. | 
 |  | 
 | [texture-manager]: https://chromium.googlesource.com/chromium/src/+/master/gpu/command_buffer/service/texture_manager.cc |