blob: 9cb8bf0dac420a82ce46ef70c206fb196ec60ed7 [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
erikchenfd7bb6c2018-03-22 18:04:1965 4. To navigate allocations, select a frame in the right-side pane and press
66 Enter/Return. To pop up the stack, press Backspace/Delete.
hjd0304f112016-11-14 22:36:5367
68[memory-infra]: README.md
69[m-purple]: https://storage.googleapis.com/chromium-docs.appspot.com/d7bdf4d16204c293688be2e5a0bcb2bf463dbbc3
70[cells-heap-dump]: https://storage.googleapis.com/chromium-docs.appspot.com/a24d80d6a08da088e2e9c8b2b64daa215be4dacb
71
erikchenf98fd8c2018-02-01 19:55:5572## How to automatically extract large allocations from a heap dump
hjd0304f112016-11-14 22:36:5373
erikchenf98fd8c2018-02-01 19:55:5574 1. Run `python ./third_party/catapult/experimental/tracing/bin/diff_heap_profiler.py
75 <path_to_trace>`
erikchenffe16492017-06-23 00:43:2776
erikchenf98fd8c2018-02-01 19:55:5577 2. This produces a directory `output`, which contains a JSON file.
erikchenffe16492017-06-23 00:43:2778
erikchenf98fd8c2018-02-01 19:55:5579 3. Load the contents of the JSON file in any JSON viewer, e.g.
80 [jsonviewer](http://jsonviewer.stack.hu/).
erikchenffe16492017-06-23 00:43:2781
erikchenf98fd8c2018-02-01 19:55:5582 4. The JSON files shows allocations segmented by stacktrace, sorted by largest
83 first.
hjd0304f112016-11-14 22:36:5384
85## Heap Details
86
87The heap details view contains a tree that represents the heap. The size of the
88root node corresponds to the selected allocator cell.
89
90*** aside
91The size value in the heap details view will not match the value in the selected
92analysis view cell exactly. There are three reasons for this. First, the heap
93profiler reports the memory that _the program requested_, whereas the allocator
94reports the memory that it _actually allocated_ plus its own bookkeeping
95overhead. Second, allocations that happen early --- before Chrome knows that
96heap profiling is enabled --- are not captured by the heap profiler, but they
97are reported by the allocator. Third, tracing overhead is not discounted by the
98heap profiler.
99***
100
101The heap can be broken down in two ways: by _backtrace_ (marked with an ƒ), and
102by _type_ (marked with a Ⓣ). When tracing is enabled, Chrome records trace
103events, most of which appear in the flame chart in timeline view. At every
104point in time these trace events form a pseudo stack, and a vertical slice
105through the flame chart is like a backtrace. This corresponds to the ƒ nodes in
106the heap details view. Hence enabling more tracing categories will give a more
107detailed breakdown of the heap.
108
109The other way to break down the heap is by object type. At the moment this is
110only supported for PartitionAlloc.
111
112*** aside
113In official builds, only the most common type names are included due to binary
114size concerns. Development builds have full type information.
115***
116
117To keep the trace log small, uninteresting information is omitted from heap
118dumps. The long tail of small nodes is not dumped, but grouped in an `<other>`
qyearsleyc0dc6f42016-12-02 22:13:39119node instead. Note that although these small nodes are insignificant on their
hjd0304f112016-11-14 22:36:53120own, together they can be responsible for a significant portion of the heap. The
121`<other>` node is large in that case.
122
123## Example
124
125In the trace below, `ParseAuthorStyleSheet` is called at some point.
126
127![ParseAuthorStyleSheet pseudo stack][pseudo-stack]
128
129The pseudo stack of trace events corresponds to the tree of ƒ nodes below. Of
130the 23.5 MiB of memory allocated with PartitionAlloc, 1.9 MiB was allocated
131inside `ParseAuthorStyleSheet`, either directly, or at a deeper level (like
132`CSSParserImpl::parseStyleSheet`).
133
134![Memory Allocated in ParseAuthorStyleSheet][break-down-by-backtrace]
135
136By expanding `ParseAuthorStyleSheet`, we can see which types were allocated
137there. Of the 1.9 MiB, 371 KiB was spent on `ImmutableStylePropertySet`s, and
138238 KiB was spent on `StringImpl`s.
139
140![ParseAuthorStyleSheet broken down by type][break-down-by-type]
141
142It is also possible to break down by type first, and then by backtrace. Below
143we see that of the 23.5 MiB allocated with PartitionAlloc, 1 MiB is spent on
144`Node`s, and about half of the memory spent on nodes was allocated in
145`HTMLDocumentParser`.
146
147![The PartitionAlloc heap broken down by type first and then by backtrace][type-then-backtrace]
148
149Heap dump diffs are fully supported by trace viewer. Select a heavy memory dump
150(a purple dot), then with the control key select a heavy memory dump earlier in
151time. Below is a diff of theverge.com before and in the middle of loading ads.
152We can see that 4 MiB were allocated when parsing the documents in all those
153iframes, almost a megabyte of which was due to JavaScript. (Note that this is
154memory allocated by PartitionAlloc alone, the total renderer memory increase was
155around 72 MiB.)
156
157![Diff of The Verge before and after loading ads][diff]
158
159[pseudo-stack]: https://storage.googleapis.com/chromium-docs.appspot.com/058e50350836f55724e100d4dbbddf4b9803f550
160[break-down-by-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.com/ec61c5f15705f5bcf3ca83a155ed647a0538bbe1
161[break-down-by-type]: https://storage.googleapis.com/chromium-docs.appspot.com/2236e61021922c0813908c6745136953fa20a37b
162[type-then-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.com/c5367dde11476bdbf2d5a1c51674148915573d11
163[diff]: https://storage.googleapis.com/chromium-docs.appspot.com/802141906869cd533bb613da5f91bd0b071ceb24