blob: d22b6529e31aa1df005dd3ab7a99e421e7be1634 [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
Erik Chenfadc10b462019-03-19 23:15:567By default, MemoryInfra traces will not contain heap dumps. Heap profiling must
8be enabled via chrome://memory-internals or about://flags.
9
hjd0304f112016-11-14 22:36:5310[TOC]
11
erikchenf98fd8c2018-02-01 19:55:5512## How to obtain a heap dump (M66+, Linux, macOS, Windows)
hjd0304f112016-11-14 22:36:5313
Erik Chenfadc10b462019-03-19 23:15:5614 1. Navigate to chrome://memory-internals.
15 * There will be an error message at the top if heap-profiling is not
16 supported on the current configuration
17 2. Enable heap profiling for the relevant processes. Future allocations will be
18 tracked. Refresh the page to view tracked processes.
19 * To enable tracking at process start, navigate to chrome://flags and search
20 for `memlog`.
21 3. To take a heap dump, click `save dump`. This is stored as a
22 [MemoryInfra][memory-infra] trace.
23 4. To symbolize the trace:
erikchen005071b2018-08-30 20:07:3624 * Windows only: build `addr2line-pdb` from the chromium repository. For subsequent commands, add the flag `--addr2line-executable=<path_to_addr2lin-pdb>`
25 * If this is a local build, run the command `./third_party/catapult/tracing/bin/symbolize_trace --is-local-build <path_to_trace>`
26 * If this is an official Chrome build, run `./third_party/catapult/tracing/bin/symbolize_trace <path_to_trace>`. This will request authentication with google cloud storage to obtain symbol files [googlers only].
27 * If this is an official macOS or Linux Chrome build, add the flag `--use-breakpad-symbols`.
Erik Chendffc12c2021-03-31 01:08:2428 * If the trace is from a different device on the same operating system, add the flag
29 `--only-symbolize-chrome-symbols`.
30 * If you run into the error "Nothing to symbolize" then backtraces are not
31 working properly. There are two mechanisms that Chrome attempts to use:
32 frame pointers if they're present, and backtrace lib. The former can be
ssidc791b8b2021-06-24 02:13:1933 forced on with enable_frame_pointers gn arg. This should work on all architectures except for
34 arm 32. The latter depends on unwind tables.
Erik Chenfadc10b462019-03-19 23:15:5635 5. Load the (now symbolized) trace in chrome://tracing.
erikchenf98fd8c2018-02-01 19:55:5536
37## How to obtain a heap dump (M66+, Android)
38
ssidc791b8b2021-06-24 02:13:1939On arm64 and x86-64, you can build chrome normally and follow steps above to
40obtain heap dumps.
erikchenf98fd8c2018-02-01 19:55:5541
ssidc791b8b2021-06-24 02:13:1942To obtain native heap dumps on arm32, you will need a custom build of Chrome
43with the GN arguments `enable_profiling = true`, `arm_use_thumb = false`,
44`is_component_build = false` and `symbol_level=1`. All other steps are the same.
45
46Alternatively, if you want to use an official build of Chrome, use
47`is_official_build = true` for arm32. If you want to use a released build,
48profiling only works on Dev and Canary on arm, and all channels on x86-64. In
49this case, you also need to fetch symbols manually and pass to the
50symbolize_trace script above.
erikchenf98fd8c2018-02-01 19:55:5551
52## How to obtain a heap dump (M65 and older)
53
54For the most part, the setting `enable-heap-profiling` in `chrome://flags` has a
55similar effect to the various `memlog` flags.
56
57
58## How to manually browse a heap dump
59
60 1. Select a heavy memory dump indicated by a purple ![M][m-purple] dot.
61
62 2. In the analysis view, cells marked with a triple bar icon (☰) contain heap
hjd0304f112016-11-14 22:36:5363 dumps. Select such a cell.
64
65 ![Cells containing a heap dump][cells-heap-dump]
66
erikchenf98fd8c2018-02-01 19:55:5567 3. Scroll down all the way to _Heap Details_.
hjd0304f112016-11-14 22:36:5368
erikchenfd7bb6c2018-03-22 18:04:1969 4. To navigate allocations, select a frame in the right-side pane and press
70 Enter/Return. To pop up the stack, press Backspace/Delete.
hjd0304f112016-11-14 22:36:5371
72[memory-infra]: README.md
73[m-purple]: https://storage.googleapis.com/chromium-docs.appspot.com/d7bdf4d16204c293688be2e5a0bcb2bf463dbbc3
74[cells-heap-dump]: https://storage.googleapis.com/chromium-docs.appspot.com/a24d80d6a08da088e2e9c8b2b64daa215be4dacb
75
erikchenf98fd8c2018-02-01 19:55:5576## How to automatically extract large allocations from a heap dump
hjd0304f112016-11-14 22:36:5377
erikchenf98fd8c2018-02-01 19:55:5578 1. Run `python ./third_party/catapult/experimental/tracing/bin/diff_heap_profiler.py
79 <path_to_trace>`
erikchenffe16492017-06-23 00:43:2780
erikchenf98fd8c2018-02-01 19:55:5581 2. This produces a directory `output`, which contains a JSON file.
erikchenffe16492017-06-23 00:43:2782
erikchenf98fd8c2018-02-01 19:55:5583 3. Load the contents of the JSON file in any JSON viewer, e.g.
84 [jsonviewer](http://jsonviewer.stack.hu/).
erikchenffe16492017-06-23 00:43:2785
erikchenf98fd8c2018-02-01 19:55:5586 4. The JSON files shows allocations segmented by stacktrace, sorted by largest
87 first.
hjd0304f112016-11-14 22:36:5388
89## Heap Details
90
91The heap details view contains a tree that represents the heap. The size of the
92root node corresponds to the selected allocator cell.
93
94*** aside
95The size value in the heap details view will not match the value in the selected
96analysis view cell exactly. There are three reasons for this. First, the heap
97profiler reports the memory that _the program requested_, whereas the allocator
98reports the memory that it _actually allocated_ plus its own bookkeeping
99overhead. Second, allocations that happen early --- before Chrome knows that
100heap profiling is enabled --- are not captured by the heap profiler, but they
101are reported by the allocator. Third, tracing overhead is not discounted by the
102heap profiler.
103***
104
105The heap can be broken down in two ways: by _backtrace_ (marked with an ƒ), and
106by _type_ (marked with a Ⓣ). When tracing is enabled, Chrome records trace
107events, most of which appear in the flame chart in timeline view. At every
108point in time these trace events form a pseudo stack, and a vertical slice
109through the flame chart is like a backtrace. This corresponds to the ƒ nodes in
110the heap details view. Hence enabling more tracing categories will give a more
111detailed breakdown of the heap.
112
113The other way to break down the heap is by object type. At the moment this is
114only supported for PartitionAlloc.
115
116*** aside
117In official builds, only the most common type names are included due to binary
118size concerns. Development builds have full type information.
119***
120
121To keep the trace log small, uninteresting information is omitted from heap
122dumps. The long tail of small nodes is not dumped, but grouped in an `<other>`
qyearsleyc0dc6f42016-12-02 22:13:39123node instead. Note that although these small nodes are insignificant on their
hjd0304f112016-11-14 22:36:53124own, together they can be responsible for a significant portion of the heap. The
125`<other>` node is large in that case.
126
127## Example
128
129In the trace below, `ParseAuthorStyleSheet` is called at some point.
130
131![ParseAuthorStyleSheet pseudo stack][pseudo-stack]
132
133The pseudo stack of trace events corresponds to the tree of ƒ nodes below. Of
134the 23.5 MiB of memory allocated with PartitionAlloc, 1.9 MiB was allocated
135inside `ParseAuthorStyleSheet`, either directly, or at a deeper level (like
136`CSSParserImpl::parseStyleSheet`).
137
138![Memory Allocated in ParseAuthorStyleSheet][break-down-by-backtrace]
139
140By expanding `ParseAuthorStyleSheet`, we can see which types were allocated
141there. Of the 1.9 MiB, 371 KiB was spent on `ImmutableStylePropertySet`s, and
142238 KiB was spent on `StringImpl`s.
143
144![ParseAuthorStyleSheet broken down by type][break-down-by-type]
145
146It is also possible to break down by type first, and then by backtrace. Below
147we see that of the 23.5 MiB allocated with PartitionAlloc, 1 MiB is spent on
148`Node`s, and about half of the memory spent on nodes was allocated in
149`HTMLDocumentParser`.
150
151![The PartitionAlloc heap broken down by type first and then by backtrace][type-then-backtrace]
152
153Heap dump diffs are fully supported by trace viewer. Select a heavy memory dump
154(a purple dot), then with the control key select a heavy memory dump earlier in
155time. Below is a diff of theverge.com before and in the middle of loading ads.
156We can see that 4 MiB were allocated when parsing the documents in all those
157iframes, almost a megabyte of which was due to JavaScript. (Note that this is
158memory allocated by PartitionAlloc alone, the total renderer memory increase was
159around 72 MiB.)
160
161![Diff of The Verge before and after loading ads][diff]
162
163[pseudo-stack]: https://storage.googleapis.com/chromium-docs.appspot.com/058e50350836f55724e100d4dbbddf4b9803f550
164[break-down-by-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.com/ec61c5f15705f5bcf3ca83a155ed647a0538bbe1
165[break-down-by-type]: https://storage.googleapis.com/chromium-docs.appspot.com/2236e61021922c0813908c6745136953fa20a37b
166[type-then-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.com/c5367dde11476bdbf2d5a1c51674148915573d11
167[diff]: https://storage.googleapis.com/chromium-docs.appspot.com/802141906869cd533bb613da5f91bd0b071ceb24