Albert J. Wong | 34b06ef | 2018-01-11 18:57:26 | [diff] [blame] | 1 | # Description of Tools for developers trying to understand memory usage |
| 2 | |
| 3 | This page provides an overview of the tools available for examining memory usage |
| 4 | in chrome. |
| 5 | |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 6 | ## Which tool should I use? |
Albert J. Wong | 34b06ef | 2018-01-11 18:57:26 | [diff] [blame] | 7 | |
| 8 | No single tool can give a full view of memory usage in Chrome. There are too |
| 9 | many different context involved (JS heap, DOM objects, native allocations, GPU, |
| 10 | etc) that any tool that collected all that information likely would not be able |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 11 | to provide an actionable analysis. |
| 12 | |
| 13 | Here is a table of common area of inquiry and suggested tools for examining them. |
Albert J. Wong | 34b06ef | 2018-01-11 18:57:26 | [diff] [blame] | 14 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 15 | | Topic/Area of Inquiry | Tool(s) | |
| 16 | |----------------------- | ------- | |
| 17 | | Which subsystems consuming memory per process. | [Global Memory Dumps](#global-memory-dumps), [Taking memory-infra trace](#memory-infra-trace) | |
| 18 | | Tracking C++ object allocation over time | [`diff_heap_profiler.py`](#diff-heap-profiler), [Heap Details in chrome://tracing](#heap-dumps-chrome-tracing) | |
Kevin Babbitt | dfa8c8c | 2023-11-16 16:41:40 | [diff] [blame^] | 19 | | Suspected DOM leaks in the Renderer | [Developer Tools Heap Snapshots](#dev-tools-heap-snapshots), [Real World Leak Detector](#real-world-leak-detector) | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 20 | | Kernel/Driver Memory and Resource Usage | [perfmon (win), ETW](#os-tools) | |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 21 | | Blackbox examination of process memory | [VMMAP (win)](#os-tools) | Understanding fragmentation of the memory space | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 22 | | Symbolized Heap Dump data | [Heap Dumps](#heap-dumps) | Grabs raw data for analysis by other tools | |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 23 | |
| 24 | If that seems like a lot of tools and complexity, it is [but there's a reason](#no-one-true-metric). |
| 25 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 26 | ----------- |
| 27 | ## <a name="global-memory-dumps"> Global Memory Dumps |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 28 | Many Chrome subsystems implement the |
Amos Lim | f916d57 | 2018-05-21 23:10:35 | [diff] [blame] | 29 | [`trace_event::MemoryDumpProvider`](../../base/trace_event/memory_dump_provider.h) |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 30 | interface to provide self-reported stats detailing their memory usage. The |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 31 | Global Memory Dump view provides a snapshot-oriented view of these subsystems |
| 32 | that can be collected and viewed via the chrome://tracing infrastructure. |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 33 | |
| 34 | In the Analysis split screen, a single roll-up number is provided for each of |
| 35 | these subsystems. This can give a quick feel for where memory is allocated. The |
| 36 | cells can then be clicked to drill into a more detailed view of the subsystem's |
| 37 | stats. The memory-infra docs have more [detailed descriptions for each column](../memory-infra#Columns). |
| 38 | |
| 39 | To look a the delta between two dumps, control-click two different dark-purple M |
| 40 | circles. |
| 41 | |
| 42 | ### Blindspots |
Quinten Yearsley | 317532d | 2021-10-20 17:10:31 | [diff] [blame] | 43 | * Statistics are self-reported. If the MemoryDumpProvider implementation does |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 44 | not fully cover the resource usage of the subsystem, those resources will |
| 45 | not be accounted. |
| 46 | |
| 47 | ### Instructions |
| 48 | 1. Take a memory-infra trace |
| 49 | 2. Click on a *dark-purple* M circle. Each one of these corresponds to a heavy |
| 50 | dump. |
| 51 | 3. Click on a (process, subsystem) cell in `Global Memory Dump` tab within the |
| 52 | Analysis View in bottom split screen. |
| 53 | 4. *Scroll down* to the bottom of the lower split screen to see details of |
| 54 | selection (process, subsystem) |
| 55 | |
| 56 | Clicking on the cell pulls up a view that lets you examine the stats |
| 57 | collected by the given MemoryDumpProvider however that view is often way outside |
| 58 | the viewport of the analysis view. Be sure to scroll down. |
| 59 | |
| 60 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 61 | ----------- |
| 62 | ## <a name="heap-dumps-chrome-tracing"> Heap Dumps in chrome://tracing |
| 63 | GUI method of exploring the heap dump for a process. |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 64 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 65 | TODO(awong): Explain how to interpret + interact with the data. (e.g. threads, |
| 66 | bottom-up vs top-down, etc) |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 67 | |
| 68 | ### Blindspots |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 69 | * As this is a viewer of [heap dump](#heap-dump) data, it has the same |
| 70 | blindspots. |
| 71 | * The tool is bound by the memory limits of chrome://tracing. Large dumps |
| 72 | (which generate large JS strings) will not be loadable and may likely crash |
| 73 | chrome://tracing. |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 74 | |
| 75 | ### Instructions |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 76 | 1. [Configure Out-of-process heap profiling](#configure-oophp) |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 77 | 2. Take a memory-infra trace and symbolize it. |
| 78 | 3. Click on a *dark-purple* M circle. |
| 79 | 4. Find the cell corresponding to the allocator (list below) for the process of interest within the `Global Memory Dump` tab of the Analysis View. |
| 80 | 5. Click on "hotdog" menu icon next to the number. If no icon is shown, the |
| 81 | trace does not contain a heap dump for that allocator. |
| 82 | 6. *Scroll down* to the bottom of the lower split screen. There should now |
| 83 | be a "Heap details" section below the "Component details" section that |
| 84 | shows a all heap allocations in a navigatable format. |
| 85 | |
| 86 | On step 5, the `Component Details` and `Heap Dump` views that let you examine |
| 87 | the information collected by the given MemoryDumpProvider is often way outside |
| 88 | the current viewport of the Analysis View. Be sure to scroll down! |
| 89 | |
Albert J. Wong | 3948511 | 2018-01-17 23:07:51 | [diff] [blame] | 90 | Currently supported allocators: malloc, PartitionAlloc, Oilpan. |
| 91 | |
| 92 | Note: PartitionAlloc and Oilpan traces have unsymbolized Javascript frames |
| 93 | which often make exploration via this tool hard to consume. |
| 94 | |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 95 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 96 | ----------- |
| 97 | |
| 98 | ## <a name="diff-heap-profiler"></a> `diff_heap_profiler.py` |
| 99 | This is most useful for examining allocations that occur during an interval of |
| 100 | time. This is often useful for finding leaks as one call-stack will rise to the |
| 101 | top as the leak is repeated triggered. |
| 102 | |
| 103 | Multiple traces can be given at once to show incremental changes. A similar |
| 104 | analysis can be had via ctrl-clicking multiple Global Memory Dumps in the |
| 105 | chrome://tracing UI but loading multiiple detailed heapdumps can often crash the |
| 106 | chrome://tracing UI. This tool is more robust to large data sizes. |
| 107 | |
| 108 | The source code can also be used as an example for manually processing heap dump |
| 109 | data in python. |
| 110 | |
| 111 | TODO(awong): Write about options to script and the flame graph. |
| 112 | |
| 113 | ### Blindspots |
| 114 | * As this is a viewer of [heap dump](#heap-dumps) data, it has the same |
| 115 | blindspots. |
| 116 | |
| 117 | ### Instructions |
| 118 | 1. Get 2 or more [symbolized heap dump](#heap-dumps) |
John Palmer | 046f987 | 2021-05-24 01:24:56 | [diff] [blame] | 119 | 3. Run resulting traces through [`diff_heap_profiler.py`](https://chromium.googlesource.com/catapult/+/main/experimental/tracing/bin/diff_heap_profiler.py) to show a list of new allocations. |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 120 | |
| 121 | ----------- |
| 122 | ## <a name="heap-dumps"></a>Heap Dumps |
| 123 | Heap dumps provide extremely detailed data about object allocations and is |
| 124 | useful for finding code locations that are generating a large number of live |
| 125 | allocations. Data is tracked and recorded using the [Out-of-process Heap |
Amos Lim | f916d57 | 2018-05-21 23:10:35 | [diff] [blame] | 126 | Profiler (OOPHP)](../../components/services/heap_profiling/README.md). |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 127 | |
| 128 | For the Browser and GPU process, this often quickly finds objects that leak over |
| 129 | time. |
| 130 | |
| 131 | This is less useful in the Renderer process. Even though Oilpan and |
| 132 | PartitionAlloc are hooked into the data collection, many of the stacks end up |
| 133 | looking similar due to the nature of DOM node allocation. |
| 134 | |
| 135 | ### Blindspots |
| 136 | * Heap dumps only catch allocations that pass through the allocator shim. In particular, |
| 137 | calls made directly to the platform's VM subsystem (eg, via `mmap()` or |
| 138 | `VirtualAlloc()`) will not be tracked. |
| 139 | * Utility processes are currently not profiled. |
| 140 | * Allocations are only recorded after the |
Amos Lim | f916d57 | 2018-05-21 23:10:35 | [diff] [blame] | 141 | [HeapProfilingService](../../components/services/heap_profiling/heap_profiling_service.h) |
erikchen | fa983faa | 2018-04-05 18:56:42 | [diff] [blame] | 142 | has spun up the profiling process and created a connection to the target |
| 143 | process. The HeapProfilingService is a mojo service that can be configured to |
| 144 | start early in browser startup but it still takes time to spin up and early |
| 145 | allocations are thus lost. |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 146 | |
| 147 | ### Instructions |
| 148 | #### <a name="configure-oophp"></a>Configuration and setup |
| 149 | 1. [Android Only] For native stack traces, a custom build with |
Darwin Huang | 6ba4756 | 2019-12-18 21:28:59 | [diff] [blame] | 150 | `enable_framepointers=true` is required. |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 151 | 2. Configure OOPHP settings in about://flags. (See table below) |
| 152 | 3. Restart browser with new settings if necessary. |
| 153 | 4. Verify target processes are being profiled in chrome://memory-internals. |
| 154 | 5. [Optional] start profiling additional processes in chrome://memory-internals. |
| 155 | |
| 156 | | Flag | Notes | |
| 157 | | ------- | ----- | |
| 158 | | Out of process heap profiling start mode. | This option is somewhat misnamed. It tells OOPHP which processes to profile at startup. Other processes can selected manually later via chrome://memory-internals even if this is set to "disabled". | |
| 159 | | Keep track of even the small allocations in memlog heap dumps. | By default, small allocations are not emitted in the heap dump to reduce dump size. Enabling this track _all_ allocations. | |
Quinten Yearsley | 317532d | 2021-10-20 17:10:31 | [diff] [blame] | 160 | | The type of stack to record for memlog heap dumps | If possible, use Native stack frames as that provides the best information. When those are not available either due to performance for build (eg, no frame-pointers on arm32 official) configurations, using trace events for a "pseudo stack" can give good information too. | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 161 | | Heap profiling | Deprecated. Enables the in-process heap profiler. Functionality should be fully subsumed by preceeding options. | |
| 162 | |
| 163 | #### Saving a heap dump |
| 164 | 1. On Desktop, click "save dump" in chrome://memory-internals to save a |
| 165 | dump of all the profiled processes. On Android, enable debugging via USB |
| 166 | and use chrome://inspect/?tracing#devices to take a memory-infra trace |
| 167 | which will have the heap dump embedded. |
Erik Chen | fdf9afc | 2018-01-23 20:19:35 | [diff] [blame] | 168 | 2. Symbolize trace using [`symbolize_trace.py`](../../third_party/catapult/tracing/bin/symbolize_trace). If the Chrome binary was built locally, pass the flag "--is-local-build". |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 169 | 3. Analyze resuing heap dump using [`diff_heap_profiler.py`](#diff-heap-profiler), or [Heap Profile view in Chrome Tracing](#tracing-heap-profile) |
| 170 | |
Quinten Yearsley | 317532d | 2021-10-20 17:10:31 | [diff] [blame] | 171 | On desktop, using chrome://memory-internals to take a heap dump is more reliable |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 172 | as it directly saves the heapdump to a file instead of passing the serialized data |
| 173 | through the chrome://tracing renderer process which can easily OOM. For Android, |
| 174 | this native file saving was harder to implement and would still leave the |
| 175 | problem of getting the dump off the phone so memory-infra tracing is the |
| 176 | current recommended path. |
| 177 | |
| 178 | ----------- |
| 179 | ## <a name="memory-infra-trace"></a> Taking a memory-infra trace. |
| 180 | Examining self-reported statistics from various subsystems on memory usages. |
| 181 | This is most useful for getting a high-level understanding of how memory is |
| 182 | distributed between the different heaps and subsystems in chrome. |
| 183 | |
| 184 | It also provides a way to view heap dump allocation information collected per |
| 185 | process through a progressively expanding stack trace. |
| 186 | |
| 187 | Though chrome://tracing itself is a timeline based plot, this data is snapshot |
| 188 | oriented. Thus the standard chrome://tracing plotting tools do not provide a |
| 189 | good means for measuring changes per snapshot. |
| 190 | |
| 191 | ### Blindspots |
| 192 | * Statistics are self-reported via "Memory Dump Provider" interfaces. If there |
| 193 | is an error in the data collection, or if there are privileged resources |
| 194 | that cannot be easily measured from usermode, they will be missed. |
| 195 | |
| 196 | ### Instructions |
| 197 | 1. Visit chrome://tracing |
| 198 | 2. Start a trace for memory-infra |
| 199 | 1. Click the "Record" button |
| 200 | 2. Choose "Manually select settings" |
| 201 | 3. [optional] Clear out all other tracing categories. |
| 202 | 4. Select "memory-infra" from the "Disabled by Default Categories" |
| 203 | 5. Click record again. |
| 204 | 3. Wait for a few seconds for a Global Memory Dump to be taken. If OOPHP |
| 205 | is enabled, don't run for more than a few seconds to avoid crashing the |
| 206 | chrome://tracing UI with an over-large trace. |
| 207 | 4. Wait for a few seconds for a Global Memory Dump to be taken. |
| 208 | 5. Click stop |
| 209 | |
| 210 | This should produce a view of the trace file with periodic "light" and "heavy" |
| 211 | memory dumps. These dumps are created periodically so the time spent waiting |
| 212 | in step (3) determines how many dumps (which are snapshots) are taken. |
| 213 | |
| 214 | **Warning:** If OOPHP is enabled, the tracing UI may not be able to handle |
| 215 | deserializing or rendering the memory dump. In this situation, save |
| 216 | the heap dump directly in chrome://memory-internals and use alternate tools to |
Alexei Filippov | e024518 | 2019-03-08 20:17:05 | [diff] [blame] | 217 | analyze it. |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 218 | |
| 219 | TODO(ajwong): Add screenshot or at least reference the more detailed |
| 220 | memory-infra docs. |
| 221 | |
Kevin Babbitt | dfa8c8c | 2023-11-16 16:41:40 | [diff] [blame^] | 222 | ----------- |
| 223 | ## <a name="dev-tools-heap-snapshots"></a> Developer Tools Heap Snapshots |
| 224 | |
| 225 | Heap snapshots provide views of objects on the Oilpan and V8 heaps and retainer |
| 226 | relationships between them. General documentation is here: |
| 227 | https://developer.chrome.com/docs/devtools/memory-problems/heap-snapshots/ |
| 228 | |
| 229 | By default, many objects on the Oilpan heap will be labeled as "InternalNode". |
| 230 | To capture detailed symbol names for them, follow these steps: |
| 231 | |
| 232 | 1. Add the following to gn args and rebuild: `cppgc_enable_object_names = true` <br/> |
| 233 | Or use [Chrome for Testing](https://googlechromelabs.github.io/chrome-for-testing/) prebuilt binaries; they have this flag enabled. |
| 234 | |
| 235 | 2. In Developer Tools, under Settings | Experiments, check "Show option to |
| 236 | expose internals in heap snapshots" |
| 237 | |
| 238 | 3. Reload Developer Tools (there will be a button for this at the top of the |
| 239 | window) |
| 240 | |
| 241 | 4. On the Memory pane, under Select profiling type | Heap snapshot, check |
| 242 | "Expose internals (includes additional implementation-specific details)" |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 243 | |
| 244 | ----------- |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 245 | ## <a name="real-world-leak-detector"></a> Real World Leak Detector (Blink-only) |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 246 | TODO(awong): Fill in. |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 247 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 248 | |
| 249 | ----------- |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 250 | ## <a name="os-tools"></a> OS Tools: perfmon, ETW, VMMAP |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 251 | Each OS provides specialized tools that give the closest to complete information |
| 252 | about resource usage. This is a list of commonly interesting tools per platform. |
| 253 | Use them as search terms to look up new ways to analyze data. |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 254 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 255 | | Platform | Tools | |
| 256 | | -------- | ----- | |
| 257 | | Window | [SysInternals vmmap](https://docs.microsoft.com/en-us/sysinternals/downloads/vmmap), resmon (can track kernel resources like Paged Pool), perfmon, ETW, !heap in WinDbg | |
| 258 | | Mac | [vmmap](https://developer.apple.com/library/content/documentation/Performance/Conceptual/ManagingMemory/Articles/VMPages.html), `vm_stat` | |
| 259 | | Linux/Android | `cat /proc/pid/maps` | |
| 260 | |
| 261 | |
| 262 | ----------- |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 263 | ## <a name="no-one-true-metric"></a> No really, I want one tool/metric that views everything. Can I has it plz? |
| 264 | Sorry. No. |
| 265 | |
Albert J. Wong | 17417476 | 2018-01-18 23:50:23 | [diff] [blame] | 266 | There is a natural tradeoff between getting detailed information |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 267 | and getting reliably complete information. Getting detailed information requires |
| 268 | instrumentation which adds complexity and selection bias to the measurement. |
| 269 | This reduces the reliability and completeness of the metric as code shifts over |
| 270 | time. |
| 271 | |
| 272 | While it might be possible to instrument a specific Chrome heap |
| 273 | (eg, PartitionAlloc or Oilpan, or even shimming malloc()) to gather detailed |
| 274 | actionable data, this implicitly means the instrumentation code is making |
| 275 | assumptions about what process resources are used which may not be complete |
| 276 | or correct. |
| 277 | |
| 278 | As an example of missed coverage, none of these collection methods |
| 279 | can notice kernel resources that are allocated (eg, GPU memory, or drive memory |
| 280 | such as the Windows Paged and Non-paged pools) as side effects of user mode |
| 281 | calls nor do they account for memory that does not go through new/malloc |
| 282 | (manulaly callling `mmap()`, or `VirtualAlloc()`). Querying a full view of |
Quinten Yearsley | 317532d | 2021-10-20 17:10:31 | [diff] [blame] | 283 | these allocations usually requires admin privileges, the semantics change |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 284 | per platform, and the performance can vary from being "constant-ish" to |
| 285 | being dependent on virtual space size (eg, probing allocation via |
Quinten Yearsley | 317532d | 2021-10-20 17:10:31 | [diff] [blame] | 286 | VirtualQueryEx or parsing /proc/self/maps) or number of processes in the |
Albert J. Wong | 2db98ee2 | 2018-01-16 23:17:07 | [diff] [blame] | 287 | system (NTQuerySystemInformation). |
| 288 | |
| 289 | As an example of error in measurement, PartitionAlloc did not account for |
| 290 | the Windows Committed Memory model [bug](https://crbug.com/765406) leading to |
| 291 | a "commit leak" in Windows that was undetected in its self-reported stats. |
| 292 | |
| 293 | Relying on a single metric or single tool will thus either selection bias |
| 294 | the data being read or not give enough detail to quickly act on problems. |