OLD | NEW |
(Empty) | |
| 1 # Heap Profiling with MemoryInfra |
| 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://drive.google.com/uc?id=0Bx14iZPZRgb5RFFGc0xZZEJWVFk |
| 34 [cells-heap-dump]: https://drive.google.com/uc?id=0Bx14iZPZRgb5NGlJSFRONTFoWEU |
| 35 |
| 36 ## Heap Details |
| 37 |
| 38 The heap details view contains a tree that represents the heap. The size of the |
| 39 root node corresponds to the selected allocator cell. |
| 40 |
| 41 *** aside |
| 42 The size value in the heap details view will not match the value in the selected |
| 43 analysis view cell exactly. There are three reasons for this. First, the heap |
| 44 profiler reports the memory that _the program requested_, whereas the allocator |
| 45 reports the memory that it _actually allocated_ plus its own bookkeeping |
| 46 overhead. Second, allocations that happen early --- before Chrome knows that |
| 47 heap profiling is enabled --- are not captured by the heap profiler, but they |
| 48 are reported by the allocator. Third, tracing overhead is not discounted by the |
| 49 heap profiler. |
| 50 *** |
| 51 |
| 52 The heap can be broken down in two ways: by _backtrace_ (marked with an ƒ), and |
| 53 by _type_ (marked with a Ⓣ). When tracing is enabled, Chrome records trace |
| 54 events, most of which appear in the flame chart in timeline view. At every |
| 55 point in time these trace events form a pseudo stack, and a vertical slice |
| 56 through the flame chart is like a backtrace. This corresponds to the ƒ nodes in |
| 57 the heap details view. Hence enabling more tracing categories will give a more |
| 58 detailed breakdown of the heap. |
| 59 |
| 60 The other way to break down the heap is by object type. At the moment this is |
| 61 only supported for PartitionAlloc. |
| 62 |
| 63 *** aside |
| 64 In official builds, only the most common type names are included due to binary |
| 65 size concerns. Development builds have full type information. |
| 66 *** |
| 67 |
| 68 To keep the trace log small, uninteresting information is omitted from heap |
| 69 dumps. The long tail of small nodes is not dumped, but grouped in an `<other>` |
| 70 node instead. Note that altough these small nodes are insignificant on their |
| 71 own, together they can be responsible for a significant portion of the heap. The |
| 72 `<other>` node is large in that case. |
| 73 |
| 74 ## Example |
| 75 |
| 76 In the trace below, `ParseAuthorStyleSheet` is called at some point. |
| 77 |
| 78 ![ParseAuthorStyleSheet pseudo stack][pseudo-stack] |
| 79 |
| 80 The pseudo stack of trace events corresponds to the tree of ƒ nodes below. Of |
| 81 the 23.5 MiB of memory allocated with PartitionAlloc, 1.9 MiB was allocated |
| 82 inside `ParseAuthorStyleSheet`, either directly, or at a deeper level (like |
| 83 `CSSParserImpl::parseStyleSheet`). |
| 84 |
| 85 ![Memory Allocated in ParseAuthorStyleSheet][break-down-by-backtrace] |
| 86 |
| 87 By expanding `ParseAuthorStyleSheet`, we can see which types were allocated |
| 88 there. Of the 1.9 MiB, 371 KiB was spent on `ImmutableStylePropertySet`s, and |
| 89 238 KiB was spent on `StringImpl`s. |
| 90 |
| 91 ![ParseAuthorStyleSheet broken down by type][break-down-by-type] |
| 92 |
| 93 It is also possible to break down by type first, and then by backtrace. Below |
| 94 we see that of the 23.5 MiB allocated with PartitionAlloc, 1 MiB is spent on |
| 95 `Node`s, and about half of the memory spent on nodes was allocated in |
| 96 `HTMLDocumentParser`. |
| 97 |
| 98 ![The PartitionAlloc heap broken down by type first and then by backtrace][type-
then-backtrace] |
| 99 |
| 100 Heap dump diffs are fully supported by trace viewer. Select a heavy memory dump |
| 101 (a purple dot), then with the control key select a heavy memory dump earlier in |
| 102 time. Below is a diff of theverge.com before and in the middle of loading ads. |
| 103 We can see that 4 MiB were allocated when parsing the documents in all those |
| 104 iframes, almost a megabyte of which was due to JavaScript. (Note that this is |
| 105 memory allocated by PartitionAlloc alone, the total renderer memory increase was |
| 106 around 72 MiB.) |
| 107 |
| 108 ![Diff of The Verge before and after loading ads][diff] |
| 109 |
| 110 [pseudo-stack]: https://drive.google.com/uc?id=0Bx14iZPZRgb5M194Y2RqQ
jhoZkk |
| 111 [break-down-by-backtrace]: https://drive.google.com/uc?id=0Bx14iZPZRgb5ZDRQdGNnN
DNIazA |
| 112 [break-down-by-type]: https://drive.google.com/uc?id=0Bx14iZPZRgb5THJMYlpyT
EN2Q2s |
| 113 [type-then-backtrace]: https://drive.google.com/uc?id=0Bx14iZPZRgb5UGZFX1pDU
VpOLUU |
| 114 [diff]: https://drive.google.com/uc?id=0Bx14iZPZRgb5UzNvMmVOa
0RnQWs |
OLD | NEW |