blob: 6a3ad2da531a67f26481f2166f2fd4995dd83705 [file] [log] [blame] [view]
hjd0304f112016-11-14 22:36:531# Heap Profiling with MemoryInfra
2
erikchenf98fd8c2018-02-01 19:55:553As of Chrome 48, MemoryInfra supports heap profiling. Chrome will track all live
4allocations (calls to new or malloc without a subsequent call to delete or free)
5along with sufficient metadata to identify the code that made the allocation.
hjd0304f112016-11-14 22:36:536
7[TOC]
8
erikchenf98fd8c2018-02-01 19:55:559## How to obtain a heap dump (M66+, Linux, macOS, Windows)
hjd0304f112016-11-14 22:36:5310
erikchenf98fd8c2018-02-01 19:55:5511 1. Navigate to chrome://flags and search for `memlog`.
hjd0304f112016-11-14 22:36:5312
erikchenf98fd8c2018-02-01 19:55:5513 2. Choose the process types you want to profile with the `memlog` flag. The
14 most common setting is `Only Browser`.
hjd0304f112016-11-14 22:36:5315
erikchenf98fd8c2018-02-01 19:55:5516 3. By default, small, infrequent allocations are omitted. If you want to see a
17 full heap dump, enable `memlog-keep-small-allocations`.
hjd0304f112016-11-14 22:36:5318
erikchenf98fd8c2018-02-01 19:55:5519 4. By default, stack traces use native stack traces, which does not contain any
20 thread information. To include the thread at time of allocation, set
21 `memlog-stack-mode` to `native with thread names`.
22
23 5. Restart Chrome.
24
25 6. Grab a [MemoryInfra][memory-infra] trace.
26
27 7. Save the trace.
28
29 8. Run the command `./third_party/catapult/tracing/bin/symbolize_trace
30 <path_to_trace>` to symbolize the trace. If you haven't yet done so, this
31 will require you to authenticate with google cloud storage to obtain access
32 to symbol files.
33
34 9. Turn off heap profiling in chrome://flags. Restart Chrome.
35
36 10. Load the (now symbolized) trace in chrome://tracing.
37
38## How to obtain a heap dump (M66+, Android)
39
40To obtain native heap dumps, you will need a custom build of Chrome with the GN
41arguments `enable_profiling = true`, `arm_use_thumb = false` and
42`symbol_level=1`. All other steps are the same.
43
44Alternatively, if you want to use an Official build of Chrome, navigate to
45chrome://flags and set `memlog-stack-mode` to `pseudo`. This will provide
46less-detailed stacks. The stacks also don't require symbolization.
47
48## How to obtain a heap dump (M65 and older)
49
50For the most part, the setting `enable-heap-profiling` in `chrome://flags` has a
51similar effect to the various `memlog` flags.
52
53
54## How to manually browse a heap dump
55
56 1. Select a heavy memory dump indicated by a purple ![M][m-purple] dot.
57
58 2. In the analysis view, cells marked with a triple bar icon (☰) contain heap
hjd0304f112016-11-14 22:36:5359 dumps. Select such a cell.
60
61 ![Cells containing a heap dump][cells-heap-dump]
62
erikchenf98fd8c2018-02-01 19:55:5563 3. Scroll down all the way to _Heap Details_.
hjd0304f112016-11-14 22:36:5364
erikchenf98fd8c2018-02-01 19:55:5565 4. Pinpoint the memory bug and live happily ever after.
hjd0304f112016-11-14 22:36:5366
67[memory-infra]: README.md
68[m-purple]: https://storage.googleapis.com/chromium-docs.appspot.com/d7bdf4d16204c293688be2e5a0bcb2bf463dbbc3
69[cells-heap-dump]: https://storage.googleapis.com/chromium-docs.appspot.com/a24d80d6a08da088e2e9c8b2b64daa215be4dacb
70
erikchenf98fd8c2018-02-01 19:55:5571## How to automatically extract large allocations from a heap dump
hjd0304f112016-11-14 22:36:5372
erikchenf98fd8c2018-02-01 19:55:5573 1. Run `python ./third_party/catapult/experimental/tracing/bin/diff_heap_profiler.py
74 <path_to_trace>`
erikchenffe16492017-06-23 00:43:2775
erikchenf98fd8c2018-02-01 19:55:5576 2. This produces a directory `output`, which contains a JSON file.
erikchenffe16492017-06-23 00:43:2777
erikchenf98fd8c2018-02-01 19:55:5578 3. Load the contents of the JSON file in any JSON viewer, e.g.
79 [jsonviewer](http://jsonviewer.stack.hu/).
erikchenffe16492017-06-23 00:43:2780
erikchenf98fd8c2018-02-01 19:55:5581 4. The JSON files shows allocations segmented by stacktrace, sorted by largest
82 first.
hjd0304f112016-11-14 22:36:5383
84## Heap Details
85
86The heap details view contains a tree that represents the heap. The size of the
87root node corresponds to the selected allocator cell.
88
89*** aside
90The size value in the heap details view will not match the value in the selected
91analysis view cell exactly. There are three reasons for this. First, the heap
92profiler reports the memory that _the program requested_, whereas the allocator
93reports the memory that it _actually allocated_ plus its own bookkeeping
94overhead. Second, allocations that happen early --- before Chrome knows that
95heap profiling is enabled --- are not captured by the heap profiler, but they
96are reported by the allocator. Third, tracing overhead is not discounted by the
97heap profiler.
98***
99
100The heap can be broken down in two ways: by _backtrace_ (marked with an ƒ), and
101by _type_ (marked with a Ⓣ). When tracing is enabled, Chrome records trace
102events, most of which appear in the flame chart in timeline view. At every
103point in time these trace events form a pseudo stack, and a vertical slice
104through the flame chart is like a backtrace. This corresponds to the ƒ nodes in
105the heap details view. Hence enabling more tracing categories will give a more
106detailed breakdown of the heap.
107
108The other way to break down the heap is by object type. At the moment this is
109only supported for PartitionAlloc.
110
111*** aside
112In official builds, only the most common type names are included due to binary
113size concerns. Development builds have full type information.
114***
115
116To keep the trace log small, uninteresting information is omitted from heap
117dumps. The long tail of small nodes is not dumped, but grouped in an `<other>`
qyearsleyc0dc6f42016-12-02 22:13:39118node instead. Note that although these small nodes are insignificant on their
hjd0304f112016-11-14 22:36:53119own, together they can be responsible for a significant portion of the heap. The
120`<other>` node is large in that case.
121
122## Example
123
124In the trace below, `ParseAuthorStyleSheet` is called at some point.
125
126![ParseAuthorStyleSheet pseudo stack][pseudo-stack]
127
128The pseudo stack of trace events corresponds to the tree of ƒ nodes below. Of
129the 23.5 MiB of memory allocated with PartitionAlloc, 1.9 MiB was allocated
130inside `ParseAuthorStyleSheet`, either directly, or at a deeper level (like
131`CSSParserImpl::parseStyleSheet`).
132
133![Memory Allocated in ParseAuthorStyleSheet][break-down-by-backtrace]
134
135By expanding `ParseAuthorStyleSheet`, we can see which types were allocated
136there. Of the 1.9 MiB, 371 KiB was spent on `ImmutableStylePropertySet`s, and
137238 KiB was spent on `StringImpl`s.
138
139![ParseAuthorStyleSheet broken down by type][break-down-by-type]
140
141It is also possible to break down by type first, and then by backtrace. Below
142we see that of the 23.5 MiB allocated with PartitionAlloc, 1 MiB is spent on
143`Node`s, and about half of the memory spent on nodes was allocated in
144`HTMLDocumentParser`.
145
146![The PartitionAlloc heap broken down by type first and then by backtrace][type-then-backtrace]
147
148Heap dump diffs are fully supported by trace viewer. Select a heavy memory dump
149(a purple dot), then with the control key select a heavy memory dump earlier in
150time. Below is a diff of theverge.com before and in the middle of loading ads.
151We can see that 4 MiB were allocated when parsing the documents in all those
152iframes, almost a megabyte of which was due to JavaScript. (Note that this is
153memory allocated by PartitionAlloc alone, the total renderer memory increase was
154around 72 MiB.)
155
156![Diff of The Verge before and after loading ads][diff]
157
158[pseudo-stack]: https://storage.googleapis.com/chromium-docs.appspot.com/058e50350836f55724e100d4dbbddf4b9803f550
159[break-down-by-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.com/ec61c5f15705f5bcf3ca83a155ed647a0538bbe1
160[break-down-by-type]: https://storage.googleapis.com/chromium-docs.appspot.com/2236e61021922c0813908c6745136953fa20a37b
161[type-then-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.com/c5367dde11476bdbf2d5a1c51674148915573d11
162[diff]: https://storage.googleapis.com/chromium-docs.appspot.com/802141906869cd533bb613da5f91bd0b071ceb24