OLD | NEW |
1 # Heap Profiling with MemoryInfra | 1 This document has moved to [//docs/memory-infra/heap_profiler.md](/docs/memory-i
nfra/heap_profiler.md). |
2 | 2 |
3 As of Chrome 48, MemoryInfra supports heap profiling. The core principle is | |
4 a solution that JustWorks™ on all platforms without patching or rebuilding, | |
5 intergrated with the chrome://tracing ecosystem. | |
6 | |
7 [TOC] | |
8 | |
9 ## How to Use | |
10 | |
11 1. Start Chrome with the `--enable-heap-profiling` switch. This will make | |
12 Chrome keep track of all allocations. | |
13 | |
14 2. Grab a [MemoryInfra][memory-infra] trace. For best results, start tracing | |
15 first, and _then_ open a new tab that you want to trace. Furthermore, | |
16 enabling more categories (besides memory-infra) will yield more detailed | |
17 information in the heap profiler backtraces. | |
18 | |
19 3. When the trace has been collected, select a heavy memory dump indicated by | |
20 a purple ![M][m-purple] dot. Heap dumps are only included in heavy memory | |
21 dumps. | |
22 | |
23 4. In the analysis view, cells marked with a triple bar icon (☰) contain heap | |
24 dumps. Select such a cell. | |
25 | |
26 ![Cells containing a heap dump][cells-heap-dump] | |
27 | |
28 5. Scroll down all the way to _Heap Details_. | |
29 | |
30 6. Pinpoint the memory bug and live happily ever after. | |
31 | |
32 [memory-infra]: memory_infra.md | |
33 [m-purple]: https://storage.googleapis.com/chromium-docs.appspot.com/d7bd
f4d16204c293688be2e5a0bcb2bf463dbbc3 | |
34 [cells-heap-dump]: https://storage.googleapis.com/chromium-docs.appspot.com/a24d
80d6a08da088e2e9c8b2b64daa215be4dacb | |
35 | |
36 ### Native stack traces | |
37 | |
38 By default heap profiling collects pseudo allocation traces, which are based | |
39 on trace events. I.e. frames in allocation traces correspond to trace events | |
40 that were active at the time of allocations, and are not real function names. | |
41 However, you can build a special Linux / Android build that will collect | |
42 real C/C++ stack traces. | |
43 | |
44 1. Build with the following GN flags: | |
45 | |
46 Linux | |
47 | |
48 enable_profiling = true | |
49 | |
50 | |
51 Android | |
52 | |
53 arm_use_thumb = false | |
54 enable_profiling = true | |
55 | |
56 2. Start Chrome with `--enable-heap-profiling=native` switch (notice | |
57 `=native` part). | |
58 | |
59 On Android use the command line tool before starting the app: | |
60 | |
61 build/android/adb_chrome_public_command_line --enable-heap-profiling=nat
ive | |
62 | |
63 (run the tool with an empty argument `''` to clear the command line) | |
64 | |
65 3. Grab a [MemoryInfra][memory-infra] trace. You don't need any other | |
66 categories besides `memory-infra`. | |
67 | |
68 4. Save the grabbed trace file. This step is needed because freshly | |
69 taken trace file contains raw addresses (which look like `pc:dcf5dbf8`) | |
70 instead of function names, and needs to be symbolized. | |
71 | |
72 4. Symbolize the trace file. During symbolization addresses are resolved to | |
73 the corresponding function names and trace file is rewritten (but a back
up | |
74 is saved with `.BACKUP` extension). | |
75 | |
76 Linux | |
77 | |
78 third_party/catapult/tracing/bin/symbolize_trace <trace file> | |
79 | |
80 Android | |
81 | |
82 third_party/catapult/tracing/bin/symbolize_trace --output-directory out/
Release <trace file> | |
83 | |
84 (note `--output-directory` and make sure it's right for your setup) | |
85 | |
86 5. Load the trace file in `chrome://tracing`. Locate a purple ![M][m-purple] | |
87 dot, and continue from step *3* from the instructions above. Native stac
k | |
88 traces will be shown in the _Heap Details_ pane. | |
89 | |
90 ## Heap Details | |
91 | |
92 The heap details view contains a tree that represents the heap. The size of the | |
93 root node corresponds to the selected allocator cell. | |
94 | |
95 *** aside | |
96 The size value in the heap details view will not match the value in the selected | |
97 analysis view cell exactly. There are three reasons for this. First, the heap | |
98 profiler reports the memory that _the program requested_, whereas the allocator | |
99 reports the memory that it _actually allocated_ plus its own bookkeeping | |
100 overhead. Second, allocations that happen early --- before Chrome knows that | |
101 heap profiling is enabled --- are not captured by the heap profiler, but they | |
102 are reported by the allocator. Third, tracing overhead is not discounted by the | |
103 heap profiler. | |
104 *** | |
105 | |
106 The heap can be broken down in two ways: by _backtrace_ (marked with an ƒ), and | |
107 by _type_ (marked with a Ⓣ). When tracing is enabled, Chrome records trace | |
108 events, most of which appear in the flame chart in timeline view. At every | |
109 point in time these trace events form a pseudo stack, and a vertical slice | |
110 through the flame chart is like a backtrace. This corresponds to the ƒ nodes in | |
111 the heap details view. Hence enabling more tracing categories will give a more | |
112 detailed breakdown of the heap. | |
113 | |
114 The other way to break down the heap is by object type. At the moment this is | |
115 only supported for PartitionAlloc. | |
116 | |
117 *** aside | |
118 In official builds, only the most common type names are included due to binary | |
119 size concerns. Development builds have full type information. | |
120 *** | |
121 | |
122 To keep the trace log small, uninteresting information is omitted from heap | |
123 dumps. The long tail of small nodes is not dumped, but grouped in an `<other>` | |
124 node instead. Note that altough these small nodes are insignificant on their | |
125 own, together they can be responsible for a significant portion of the heap. The | |
126 `<other>` node is large in that case. | |
127 | |
128 ## Example | |
129 | |
130 In the trace below, `ParseAuthorStyleSheet` is called at some point. | |
131 | |
132 ![ParseAuthorStyleSheet pseudo stack][pseudo-stack] | |
133 | |
134 The pseudo stack of trace events corresponds to the tree of ƒ nodes below. Of | |
135 the 23.5 MiB of memory allocated with PartitionAlloc, 1.9 MiB was allocated | |
136 inside `ParseAuthorStyleSheet`, either directly, or at a deeper level (like | |
137 `CSSParserImpl::parseStyleSheet`). | |
138 | |
139 ![Memory Allocated in ParseAuthorStyleSheet][break-down-by-backtrace] | |
140 | |
141 By expanding `ParseAuthorStyleSheet`, we can see which types were allocated | |
142 there. Of the 1.9 MiB, 371 KiB was spent on `ImmutableStylePropertySet`s, and | |
143 238 KiB was spent on `StringImpl`s. | |
144 | |
145 ![ParseAuthorStyleSheet broken down by type][break-down-by-type] | |
146 | |
147 It is also possible to break down by type first, and then by backtrace. Below | |
148 we see that of the 23.5 MiB allocated with PartitionAlloc, 1 MiB is spent on | |
149 `Node`s, and about half of the memory spent on nodes was allocated in | |
150 `HTMLDocumentParser`. | |
151 | |
152 ![The PartitionAlloc heap broken down by type first and then by backtrace][type-
then-backtrace] | |
153 | |
154 Heap dump diffs are fully supported by trace viewer. Select a heavy memory dump | |
155 (a purple dot), then with the control key select a heavy memory dump earlier in | |
156 time. Below is a diff of theverge.com before and in the middle of loading ads. | |
157 We can see that 4 MiB were allocated when parsing the documents in all those | |
158 iframes, almost a megabyte of which was due to JavaScript. (Note that this is | |
159 memory allocated by PartitionAlloc alone, the total renderer memory increase was | |
160 around 72 MiB.) | |
161 | |
162 ![Diff of The Verge before and after loading ads][diff] | |
163 | |
164 [pseudo-stack]: https://storage.googleapis.com/chromium-docs.appspot.
com/058e50350836f55724e100d4dbbddf4b9803f550 | |
165 [break-down-by-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.
com/ec61c5f15705f5bcf3ca83a155ed647a0538bbe1 | |
166 [break-down-by-type]: https://storage.googleapis.com/chromium-docs.appspot.
com/2236e61021922c0813908c6745136953fa20a37b | |
167 [type-then-backtrace]: https://storage.googleapis.com/chromium-docs.appspot.
com/c5367dde11476bdbf2d5a1c51674148915573d11 | |
168 [diff]: https://storage.googleapis.com/chromium-docs.appspot.
com/802141906869cd533bb613da5f91bd0b071ceb24 | |
OLD | NEW |