xref: /aosp_15_r20/external/perfetto/docs/case-studies/memory.md (revision 6dbdd20afdafa5e3ca9b8809fa73465d530080dc)
1*6dbdd20aSAndroid Build Coastguard Worker# Debugging memory usage on Android
2*6dbdd20aSAndroid Build Coastguard Worker
3*6dbdd20aSAndroid Build Coastguard Worker## Prerequisites
4*6dbdd20aSAndroid Build Coastguard Worker
5*6dbdd20aSAndroid Build Coastguard Worker* A host running macOS or Linux.
6*6dbdd20aSAndroid Build Coastguard Worker* [ADB](https://developer.android.com/studio/command-line/adb) installed and
7*6dbdd20aSAndroid Build Coastguard Worker  in PATH.
8*6dbdd20aSAndroid Build Coastguard Worker* A device running Android 11+.
9*6dbdd20aSAndroid Build Coastguard Worker
10*6dbdd20aSAndroid Build Coastguard WorkerIf you are profiling your own app and are not running a userdebug build of
11*6dbdd20aSAndroid Build Coastguard WorkerAndroid, your app needs to be marked as profileable or
12*6dbdd20aSAndroid Build Coastguard Workerdebuggable in its manifest. See the [heapprofd documentation](
13*6dbdd20aSAndroid Build Coastguard Worker/docs/data-sources/native-heap-profiler.md#heapprofd-targets) for more
14*6dbdd20aSAndroid Build Coastguard Workerdetails on which applications can be targeted.
15*6dbdd20aSAndroid Build Coastguard Worker
16*6dbdd20aSAndroid Build Coastguard Worker## dumpsys meminfo
17*6dbdd20aSAndroid Build Coastguard Worker
18*6dbdd20aSAndroid Build Coastguard WorkerA good place to get started investigating memory usage of a process is
19*6dbdd20aSAndroid Build Coastguard Worker`dumpsys meminfo` which gives a high-level overview of how much of the various
20*6dbdd20aSAndroid Build Coastguard Workertypes of memory are being used by a process.
21*6dbdd20aSAndroid Build Coastguard Worker
22*6dbdd20aSAndroid Build Coastguard Worker```bash
23*6dbdd20aSAndroid Build Coastguard Worker$ adb shell dumpsys meminfo com.android.systemui
24*6dbdd20aSAndroid Build Coastguard Worker
25*6dbdd20aSAndroid Build Coastguard WorkerApplications Memory Usage (in Kilobytes):
26*6dbdd20aSAndroid Build Coastguard WorkerUptime: 2030149 Realtime: 2030149
27*6dbdd20aSAndroid Build Coastguard Worker
28*6dbdd20aSAndroid Build Coastguard Worker** MEMINFO in pid 1974 [com.android.systemui] **
29*6dbdd20aSAndroid Build Coastguard Worker                   Pss  Private  Private  SwapPss      Rss     Heap     Heap     Heap
30*6dbdd20aSAndroid Build Coastguard Worker                 Total    Dirty    Clean    Dirty    Total     Size    Alloc     Free
31*6dbdd20aSAndroid Build Coastguard Worker                ------   ------   ------   ------   ------   ------   ------   ------
32*6dbdd20aSAndroid Build Coastguard Worker  Native Heap    16840    16804        0     6764    19428    34024    25037     5553
33*6dbdd20aSAndroid Build Coastguard Worker  Dalvik Heap     9110     9032        0      136    13164    36444     9111    27333
34*6dbdd20aSAndroid Build Coastguard Worker
35*6dbdd20aSAndroid Build Coastguard Worker[more stuff...]
36*6dbdd20aSAndroid Build Coastguard Worker```
37*6dbdd20aSAndroid Build Coastguard Worker
38*6dbdd20aSAndroid Build Coastguard WorkerLooking at the "Private Dirty" column of Dalvik Heap (= Java Heap) and
39*6dbdd20aSAndroid Build Coastguard WorkerNative Heap, we can see that SystemUI's memory usage on the Java heap
40*6dbdd20aSAndroid Build Coastguard Workeris 9M, on the native heap it's 17M.
41*6dbdd20aSAndroid Build Coastguard Worker
42*6dbdd20aSAndroid Build Coastguard Worker## Linux memory management
43*6dbdd20aSAndroid Build Coastguard Worker
44*6dbdd20aSAndroid Build Coastguard WorkerBut what does *clean*, *dirty*, *Rss*, *Pss*, *Swap* actually mean? To answer
45*6dbdd20aSAndroid Build Coastguard Workerthis question, we need to delve into Linux memory management a bit.
46*6dbdd20aSAndroid Build Coastguard Worker
47*6dbdd20aSAndroid Build Coastguard WorkerFrom the kernel's point of view, memory is split into equally sized blocks
48*6dbdd20aSAndroid Build Coastguard Workercalled *pages*. These are generally 4KiB.
49*6dbdd20aSAndroid Build Coastguard Worker
50*6dbdd20aSAndroid Build Coastguard WorkerPages are organized in virtually contiguous ranges called VMA
51*6dbdd20aSAndroid Build Coastguard Worker(Virtual Memory Area).
52*6dbdd20aSAndroid Build Coastguard Worker
53*6dbdd20aSAndroid Build Coastguard WorkerVMAs are created when a process requests a new pool of memory pages through
54*6dbdd20aSAndroid Build Coastguard Workerthe [mmap() system call](https://man7.org/linux/man-pages/man2/mmap.2.html).
55*6dbdd20aSAndroid Build Coastguard WorkerApplications rarely call mmap() directly. Those calls are typically mediated by
56*6dbdd20aSAndroid Build Coastguard Workerthe allocator, `malloc()/operator new()` for native processes or by the
57*6dbdd20aSAndroid Build Coastguard WorkerAndroid RunTime for Java apps.
58*6dbdd20aSAndroid Build Coastguard Worker
59*6dbdd20aSAndroid Build Coastguard WorkerVMAs can be of two types: file-backed and anonymous.
60*6dbdd20aSAndroid Build Coastguard Worker
61*6dbdd20aSAndroid Build Coastguard Worker**File-backed VMAs** are a view of a file in memory. They are obtained passing a
62*6dbdd20aSAndroid Build Coastguard Workerfile descriptor to `mmap()`. The kernel will serve page faults on the VMA
63*6dbdd20aSAndroid Build Coastguard Workerthrough the passed file, so reading a pointer to the VMA becomes the equivalent
64*6dbdd20aSAndroid Build Coastguard Workerof a `read()` on the file.
65*6dbdd20aSAndroid Build Coastguard WorkerFile-backed VMAs are used, for instance, by the dynamic linker (`ld`) when
66*6dbdd20aSAndroid Build Coastguard Workerexecuting new processes or dynamically loading libraries, or by the Android
67*6dbdd20aSAndroid Build Coastguard Workerframework, when loading a new .dex library or accessing resources in the APK.
68*6dbdd20aSAndroid Build Coastguard Worker
69*6dbdd20aSAndroid Build Coastguard Worker**Anonymous VMAs** are memory-only areas not backed by any file. This is the way
70*6dbdd20aSAndroid Build Coastguard Workerallocators request dynamic memory from the kernel. Anonymous VMAs are obtained
71*6dbdd20aSAndroid Build Coastguard Workercalling `mmap(... MAP_ANONYMOUS ...)`.
72*6dbdd20aSAndroid Build Coastguard Worker
73*6dbdd20aSAndroid Build Coastguard WorkerPhysical memory is only allocated, in page granularity, once the application
74*6dbdd20aSAndroid Build Coastguard Workertries to read/write from a VMA. If you allocate 32 MiB worth of pages but only
75*6dbdd20aSAndroid Build Coastguard Workertouch one byte, your process' memory usage will only go up by 4KiB. You will
76*6dbdd20aSAndroid Build Coastguard Workerhave increased your process' *virtual memory* by 32 MiB, but its resident
77*6dbdd20aSAndroid Build Coastguard Worker*physical memory* by 4 KiB.
78*6dbdd20aSAndroid Build Coastguard Worker
79*6dbdd20aSAndroid Build Coastguard WorkerWhen optimizing memory use of programs, we are interested in reducing their
80*6dbdd20aSAndroid Build Coastguard Workerfootprint in *physical memory*. High *virtual memory* use is generally not a
81*6dbdd20aSAndroid Build Coastguard Workercause for concern on modern platforms (except if you run out of address space,
82*6dbdd20aSAndroid Build Coastguard Workerwhich is very hard on 64 bit systems).
83*6dbdd20aSAndroid Build Coastguard Worker
84*6dbdd20aSAndroid Build Coastguard WorkerWe call the amount a process' memory that is resident in *physical memory* its
85*6dbdd20aSAndroid Build Coastguard Worker**RSS** (Resident Set Size). Not all resident memory is equal though.
86*6dbdd20aSAndroid Build Coastguard Worker
87*6dbdd20aSAndroid Build Coastguard WorkerFrom a memory-consumption viewpoint, individual pages within a VMA can have the
88*6dbdd20aSAndroid Build Coastguard Workerfollowing states:
89*6dbdd20aSAndroid Build Coastguard Worker
90*6dbdd20aSAndroid Build Coastguard Worker* **Resident**: the page is mapped to a physical memory page. Resident pages can
91*6dbdd20aSAndroid Build Coastguard Worker  be in two states:
92*6dbdd20aSAndroid Build Coastguard Worker    * **Clean** (only for file-backed pages): the contents of the page are the
93*6dbdd20aSAndroid Build Coastguard Worker      same of the contents on-disk. The kernel can evict clean pages more easily
94*6dbdd20aSAndroid Build Coastguard Worker      in case of memory pressure. This is because if they should be needed
95*6dbdd20aSAndroid Build Coastguard Worker      again, the kernel knows it can re-create its contents by reading them from
96*6dbdd20aSAndroid Build Coastguard Worker      the underlying file.
97*6dbdd20aSAndroid Build Coastguard Worker    * **Dirty**: the contents of the page diverge from the disk, or (in most
98*6dbdd20aSAndroid Build Coastguard Worker      cases), the page has no disk backing (i.e. it's _anonymous_). Dirty pages
99*6dbdd20aSAndroid Build Coastguard Worker      cannot be evicted because doing so would cause data loss. However they can
100*6dbdd20aSAndroid Build Coastguard Worker      be swapped out on disk or ZRAM, if present.
101*6dbdd20aSAndroid Build Coastguard Worker* **Swapped**: a dirty page can be written to the swap file on disk (on most Linux
102*6dbdd20aSAndroid Build Coastguard Worker  desktop distributions) or compressed (on Android and CrOS through
103*6dbdd20aSAndroid Build Coastguard Worker  [ZRAM](https://source.android.com/devices/tech/perf/low-ram#zram)). The page
104*6dbdd20aSAndroid Build Coastguard Worker  will stay swapped until a new page fault on its virtual address happens, at
105*6dbdd20aSAndroid Build Coastguard Worker  which point the kernel will bring it back in main memory.
106*6dbdd20aSAndroid Build Coastguard Worker* **Not present**: no page fault ever happened on the page or the page was
107*6dbdd20aSAndroid Build Coastguard Worker  clean and later was evicted.
108*6dbdd20aSAndroid Build Coastguard Worker
109*6dbdd20aSAndroid Build Coastguard WorkerIt is generally more important to reduce the amount of _dirty_ memory as that
110*6dbdd20aSAndroid Build Coastguard Workercannot be reclaimed like _clean_ memory and, on Android, even if swapped in
111*6dbdd20aSAndroid Build Coastguard WorkerZRAM, will still eat part of the system memory budget.
112*6dbdd20aSAndroid Build Coastguard WorkerThis is why we looked at *Private Dirty* in the `dumpsys meminfo` example.
113*6dbdd20aSAndroid Build Coastguard Worker
114*6dbdd20aSAndroid Build Coastguard Worker*Shared* memory can be mapped into more than one process. This means VMAs in
115*6dbdd20aSAndroid Build Coastguard Workerdifferent processes refer to the same physical memory. This typically happens
116*6dbdd20aSAndroid Build Coastguard Workerwith file-backed memory of commonly used libraries (e.g., libc.so,
117*6dbdd20aSAndroid Build Coastguard Workerframework.dex) or, more rarely, when a process `fork()`s and a child process
118*6dbdd20aSAndroid Build Coastguard Workerinherits dirty memory from its parent.
119*6dbdd20aSAndroid Build Coastguard Worker
120*6dbdd20aSAndroid Build Coastguard WorkerThis introduces the concept of **PSS** (Proportional Set Size). In **PSS**,
121*6dbdd20aSAndroid Build Coastguard Workermemory that is resident in multiple processes is proportionally attributed to
122*6dbdd20aSAndroid Build Coastguard Workereach of them. If we map one 4KiB page into four processes, each of their
123*6dbdd20aSAndroid Build Coastguard Worker**PSS** will increase by 1KiB.
124*6dbdd20aSAndroid Build Coastguard Worker
125*6dbdd20aSAndroid Build Coastguard Worker#### Recap
126*6dbdd20aSAndroid Build Coastguard Worker
127*6dbdd20aSAndroid Build Coastguard Worker* Dynamically allocated memory, whether allocated through C's `malloc()`, C++'s
128*6dbdd20aSAndroid Build Coastguard Worker  `operator new()` or Java's `new X()` starts always as _anonymous_ and _dirty_,
129*6dbdd20aSAndroid Build Coastguard Worker  unless it is never used.
130*6dbdd20aSAndroid Build Coastguard Worker* If this memory is not read/written for a while, or in case of memory pressure,
131*6dbdd20aSAndroid Build Coastguard Worker  it gets swapped out on ZRAM and becomes _swapped_.
132*6dbdd20aSAndroid Build Coastguard Worker* Anonymous memory, whether _resident_ (and hence _dirty_) or _swapped_ is
133*6dbdd20aSAndroid Build Coastguard Worker  always a resource hog and should be avoided if unnecessary.
134*6dbdd20aSAndroid Build Coastguard Worker* File-mapped memory comes from code (java or native), libraries and resource
135*6dbdd20aSAndroid Build Coastguard Worker  and is almost always _clean_. Clean memory also erodes the system memory
136*6dbdd20aSAndroid Build Coastguard Worker  budget but typically application developers have less control on it.
137*6dbdd20aSAndroid Build Coastguard Worker
138*6dbdd20aSAndroid Build Coastguard Worker## Memory over time
139*6dbdd20aSAndroid Build Coastguard Worker
140*6dbdd20aSAndroid Build Coastguard Worker`dumpsys meminfo` is good to get a snapshot of the current memory usage, but
141*6dbdd20aSAndroid Build Coastguard Workereven very short memory spikes can lead to low-memory situations, which will
142*6dbdd20aSAndroid Build Coastguard Workerlead to [LMKs](#lmk). We have two tools to investigate situations like this
143*6dbdd20aSAndroid Build Coastguard Worker
144*6dbdd20aSAndroid Build Coastguard Worker* RSS High Watermark.
145*6dbdd20aSAndroid Build Coastguard Worker* Memory tracepoints.
146*6dbdd20aSAndroid Build Coastguard Worker
147*6dbdd20aSAndroid Build Coastguard Worker### RSS High Watermark
148*6dbdd20aSAndroid Build Coastguard Worker
149*6dbdd20aSAndroid Build Coastguard WorkerWe can get a lot of information from the `/proc/[pid]/status` file, including
150*6dbdd20aSAndroid Build Coastguard Workermemory information. `VmHWM` shows the maximum RSS usage the process has seen
151*6dbdd20aSAndroid Build Coastguard Workersince it was started. This value is kept updated by the kernel.
152*6dbdd20aSAndroid Build Coastguard Worker
153*6dbdd20aSAndroid Build Coastguard Worker```bash
154*6dbdd20aSAndroid Build Coastguard Worker$ adb shell cat '/proc/$(pidof com.android.systemui)/status'
155*6dbdd20aSAndroid Build Coastguard Worker[...]
156*6dbdd20aSAndroid Build Coastguard WorkerVmHWM:    256972 kB
157*6dbdd20aSAndroid Build Coastguard WorkerVmRSS:    195272 kB
158*6dbdd20aSAndroid Build Coastguard WorkerRssAnon:  30184 kB
159*6dbdd20aSAndroid Build Coastguard WorkerRssFile:  164420 kB
160*6dbdd20aSAndroid Build Coastguard WorkerRssShmem: 668 kB
161*6dbdd20aSAndroid Build Coastguard WorkerVmSwap:   43960 kB
162*6dbdd20aSAndroid Build Coastguard Worker[...]
163*6dbdd20aSAndroid Build Coastguard Worker```
164*6dbdd20aSAndroid Build Coastguard Worker
165*6dbdd20aSAndroid Build Coastguard Worker### Memory tracepoints
166*6dbdd20aSAndroid Build Coastguard Worker
167*6dbdd20aSAndroid Build Coastguard WorkerNOTE: For detailed instructions about the memory trace points see the
168*6dbdd20aSAndroid Build Coastguard Worker      [Data sources > Memory > Counters and events](
169*6dbdd20aSAndroid Build Coastguard Worker      /docs/data-sources/memory-counters.md) page.
170*6dbdd20aSAndroid Build Coastguard Worker
171*6dbdd20aSAndroid Build Coastguard WorkerWe can use Perfetto to get information about memory management events from the
172*6dbdd20aSAndroid Build Coastguard Workerkernel.
173*6dbdd20aSAndroid Build Coastguard Worker
174*6dbdd20aSAndroid Build Coastguard Worker```bash
175*6dbdd20aSAndroid Build Coastguard Worker$ adb shell perfetto \
176*6dbdd20aSAndroid Build Coastguard Worker  -c - --txt \
177*6dbdd20aSAndroid Build Coastguard Worker  -o /data/misc/perfetto-traces/trace \
178*6dbdd20aSAndroid Build Coastguard Worker<<EOF
179*6dbdd20aSAndroid Build Coastguard Worker
180*6dbdd20aSAndroid Build Coastguard Workerbuffers: {
181*6dbdd20aSAndroid Build Coastguard Worker    size_kb: 8960
182*6dbdd20aSAndroid Build Coastguard Worker    fill_policy: DISCARD
183*6dbdd20aSAndroid Build Coastguard Worker}
184*6dbdd20aSAndroid Build Coastguard Workerbuffers: {
185*6dbdd20aSAndroid Build Coastguard Worker    size_kb: 1280
186*6dbdd20aSAndroid Build Coastguard Worker    fill_policy: DISCARD
187*6dbdd20aSAndroid Build Coastguard Worker}
188*6dbdd20aSAndroid Build Coastguard Workerdata_sources: {
189*6dbdd20aSAndroid Build Coastguard Worker    config {
190*6dbdd20aSAndroid Build Coastguard Worker        name: "linux.process_stats"
191*6dbdd20aSAndroid Build Coastguard Worker        target_buffer: 1
192*6dbdd20aSAndroid Build Coastguard Worker        process_stats_config {
193*6dbdd20aSAndroid Build Coastguard Worker            scan_all_processes_on_start: true
194*6dbdd20aSAndroid Build Coastguard Worker        }
195*6dbdd20aSAndroid Build Coastguard Worker    }
196*6dbdd20aSAndroid Build Coastguard Worker}
197*6dbdd20aSAndroid Build Coastguard Workerdata_sources: {
198*6dbdd20aSAndroid Build Coastguard Worker    config {
199*6dbdd20aSAndroid Build Coastguard Worker        name: "linux.ftrace"
200*6dbdd20aSAndroid Build Coastguard Worker        ftrace_config {
201*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "mm_event/mm_event_record"
202*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "kmem/rss_stat"
203*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "kmem/ion_heap_grow"
204*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "kmem/ion_heap_shrink"
205*6dbdd20aSAndroid Build Coastguard Worker        }
206*6dbdd20aSAndroid Build Coastguard Worker    }
207*6dbdd20aSAndroid Build Coastguard Worker}
208*6dbdd20aSAndroid Build Coastguard Workerduration_ms: 30000
209*6dbdd20aSAndroid Build Coastguard Worker
210*6dbdd20aSAndroid Build Coastguard WorkerEOF
211*6dbdd20aSAndroid Build Coastguard Worker```
212*6dbdd20aSAndroid Build Coastguard Worker
213*6dbdd20aSAndroid Build Coastguard WorkerWhile it is running, take a photo if you are following along.
214*6dbdd20aSAndroid Build Coastguard Worker
215*6dbdd20aSAndroid Build Coastguard WorkerPull the file using `adb pull /data/misc/perfetto-traces/trace ~/mem-trace`
216*6dbdd20aSAndroid Build Coastguard Workerand upload to the [Perfetto UI](https://ui.perfetto.dev). This will show
217*6dbdd20aSAndroid Build Coastguard Workeroverall stats about system [ION](#ion) usage, and per-process stats to
218*6dbdd20aSAndroid Build Coastguard Workerexpand. Scroll down (or Ctrl-F for) to `com.google.android.GoogleCamera` and
219*6dbdd20aSAndroid Build Coastguard Workerexpand. This will show a timeline for various memory stats for camera.
220*6dbdd20aSAndroid Build Coastguard Worker
221*6dbdd20aSAndroid Build Coastguard Worker![Camera Memory Trace](/docs/images/trace-rss-camera.png)
222*6dbdd20aSAndroid Build Coastguard Worker
223*6dbdd20aSAndroid Build Coastguard WorkerWe can see that around 2/3 into the trace, the memory spiked (in the
224*6dbdd20aSAndroid Build Coastguard Workermem.rss.anon track). This is where I took a photo. This is a good way to see
225*6dbdd20aSAndroid Build Coastguard Workerhow the memory usage of an application reacts to different triggers.
226*6dbdd20aSAndroid Build Coastguard Worker
227*6dbdd20aSAndroid Build Coastguard Worker## Which tool to use
228*6dbdd20aSAndroid Build Coastguard Worker
229*6dbdd20aSAndroid Build Coastguard WorkerIf you want to drill down into _anonymous_ memory allocated by Java code,
230*6dbdd20aSAndroid Build Coastguard Workerlabeled by `dumpsys meminfo` as `Dalvik Heap`, see the
231*6dbdd20aSAndroid Build Coastguard Worker[Analyzing the java heap](#java-hprof) section.
232*6dbdd20aSAndroid Build Coastguard Worker
233*6dbdd20aSAndroid Build Coastguard WorkerIf you want to drill down into _anonymous_ memory allocated by native code,
234*6dbdd20aSAndroid Build Coastguard Workerlabeled by `dumpsys meminfo` as `Native Heap`, see the
235*6dbdd20aSAndroid Build Coastguard Worker[Analyzing the Native Heap](#heapprofd) section. Note that it's frequent to end
236*6dbdd20aSAndroid Build Coastguard Workerup with native memory even if your app doesn't have any C/C++ code. This is
237*6dbdd20aSAndroid Build Coastguard Workerbecause the implementation of some framework API (e.g. Regex) is internally
238*6dbdd20aSAndroid Build Coastguard Workerimplemented through native code.
239*6dbdd20aSAndroid Build Coastguard Worker
240*6dbdd20aSAndroid Build Coastguard WorkerIf you want to drill down into file-mapped memory the best option is to use
241*6dbdd20aSAndroid Build Coastguard Worker`adb shell showmap PID` (on Android) or inspect `/proc/PID/smaps`.
242*6dbdd20aSAndroid Build Coastguard Worker
243*6dbdd20aSAndroid Build Coastguard Worker
244*6dbdd20aSAndroid Build Coastguard Worker## {#lmk} Low-memory kills
245*6dbdd20aSAndroid Build Coastguard Worker
246*6dbdd20aSAndroid Build Coastguard WorkerWhen an Android device becomes low on memory, a daemon called `lmkd` will
247*6dbdd20aSAndroid Build Coastguard Workerstart killing processes in order to free up memory. Devices' strategies differ,
248*6dbdd20aSAndroid Build Coastguard Workerbut in general processes will be killed in order of descending `oom_score_adj`
249*6dbdd20aSAndroid Build Coastguard Workerscore (i.e. background apps and processes first, foreground processes last).
250*6dbdd20aSAndroid Build Coastguard Worker
251*6dbdd20aSAndroid Build Coastguard WorkerApps on Android are not killed when switching away from them. They instead
252*6dbdd20aSAndroid Build Coastguard Workerremain *cached* even after the user finishes using them. This is to make
253*6dbdd20aSAndroid Build Coastguard Workersubsequent starts of the app faster. Such apps will generally be killed
254*6dbdd20aSAndroid Build Coastguard Workerfirst (because they have a higher `oom_score_adj`).
255*6dbdd20aSAndroid Build Coastguard Worker
256*6dbdd20aSAndroid Build Coastguard WorkerWe can collect information about LMKs and `oom_score_adj` using Perfetto.
257*6dbdd20aSAndroid Build Coastguard Worker
258*6dbdd20aSAndroid Build Coastguard Worker```protobuf
259*6dbdd20aSAndroid Build Coastguard Worker$ adb shell perfetto \
260*6dbdd20aSAndroid Build Coastguard Worker  -c - --txt \
261*6dbdd20aSAndroid Build Coastguard Worker  -o /data/misc/perfetto-traces/trace \
262*6dbdd20aSAndroid Build Coastguard Worker<<EOF
263*6dbdd20aSAndroid Build Coastguard Worker
264*6dbdd20aSAndroid Build Coastguard Workerbuffers: {
265*6dbdd20aSAndroid Build Coastguard Worker    size_kb: 8960
266*6dbdd20aSAndroid Build Coastguard Worker    fill_policy: DISCARD
267*6dbdd20aSAndroid Build Coastguard Worker}
268*6dbdd20aSAndroid Build Coastguard Workerbuffers: {
269*6dbdd20aSAndroid Build Coastguard Worker    size_kb: 1280
270*6dbdd20aSAndroid Build Coastguard Worker    fill_policy: DISCARD
271*6dbdd20aSAndroid Build Coastguard Worker}
272*6dbdd20aSAndroid Build Coastguard Workerdata_sources: {
273*6dbdd20aSAndroid Build Coastguard Worker    config {
274*6dbdd20aSAndroid Build Coastguard Worker        name: "linux.process_stats"
275*6dbdd20aSAndroid Build Coastguard Worker        target_buffer: 1
276*6dbdd20aSAndroid Build Coastguard Worker        process_stats_config {
277*6dbdd20aSAndroid Build Coastguard Worker            scan_all_processes_on_start: true
278*6dbdd20aSAndroid Build Coastguard Worker        }
279*6dbdd20aSAndroid Build Coastguard Worker    }
280*6dbdd20aSAndroid Build Coastguard Worker}
281*6dbdd20aSAndroid Build Coastguard Workerdata_sources: {
282*6dbdd20aSAndroid Build Coastguard Worker    config {
283*6dbdd20aSAndroid Build Coastguard Worker        name: "linux.ftrace"
284*6dbdd20aSAndroid Build Coastguard Worker        ftrace_config {
285*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "lowmemorykiller/lowmemory_kill"
286*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "oom/oom_score_adj_update"
287*6dbdd20aSAndroid Build Coastguard Worker            ftrace_events: "ftrace/print"
288*6dbdd20aSAndroid Build Coastguard Worker            atrace_apps: "lmkd"
289*6dbdd20aSAndroid Build Coastguard Worker        }
290*6dbdd20aSAndroid Build Coastguard Worker    }
291*6dbdd20aSAndroid Build Coastguard Worker}
292*6dbdd20aSAndroid Build Coastguard Workerduration_ms: 60000
293*6dbdd20aSAndroid Build Coastguard Worker
294*6dbdd20aSAndroid Build Coastguard WorkerEOF
295*6dbdd20aSAndroid Build Coastguard Worker```
296*6dbdd20aSAndroid Build Coastguard Worker
297*6dbdd20aSAndroid Build Coastguard WorkerPull the file using `adb pull /data/misc/perfetto-traces/trace ~/oom-trace`
298*6dbdd20aSAndroid Build Coastguard Workerand upload to the [Perfetto UI](https://ui.perfetto.dev).
299*6dbdd20aSAndroid Build Coastguard Worker
300*6dbdd20aSAndroid Build Coastguard Worker![OOM Score](/docs/images/oom-score.png)
301*6dbdd20aSAndroid Build Coastguard Worker
302*6dbdd20aSAndroid Build Coastguard WorkerWe can see that the OOM score of Camera gets reduced (making it less likely
303*6dbdd20aSAndroid Build Coastguard Workerto be killed) when it is opened, and gets increased again once it is closed.
304*6dbdd20aSAndroid Build Coastguard Worker
305*6dbdd20aSAndroid Build Coastguard Worker## {#heapprofd} Analyzing the Native Heap
306*6dbdd20aSAndroid Build Coastguard Worker
307*6dbdd20aSAndroid Build Coastguard Worker**Native Heap Profiles require Android 10.**
308*6dbdd20aSAndroid Build Coastguard Worker
309*6dbdd20aSAndroid Build Coastguard WorkerNOTE: For detailed instructions about the native heap profiler and
310*6dbdd20aSAndroid Build Coastguard Worker      troubleshooting see the [Data sources > Heap profiler](
311*6dbdd20aSAndroid Build Coastguard Worker      /docs/data-sources/native-heap-profiler.md) page.
312*6dbdd20aSAndroid Build Coastguard Worker
313*6dbdd20aSAndroid Build Coastguard WorkerApplications usually get memory through `malloc` or C++'s `new` rather than
314*6dbdd20aSAndroid Build Coastguard Workerdirectly getting it from the kernel. The allocator makes sure that your memory
315*6dbdd20aSAndroid Build Coastguard Workeris more efficiently handled (i.e. there are not many gaps) and that the
316*6dbdd20aSAndroid Build Coastguard Workeroverhead from asking the kernel remains low.
317*6dbdd20aSAndroid Build Coastguard Worker
318*6dbdd20aSAndroid Build Coastguard WorkerWe can log the native allocations and frees that a process does using
319*6dbdd20aSAndroid Build Coastguard Worker*heapprofd*. The resulting profile can be used to attribute memory usage
320*6dbdd20aSAndroid Build Coastguard Workerto particular function callstacks, supporting a mix of both native and Java
321*6dbdd20aSAndroid Build Coastguard Workercode. The profile *will only show allocations done while it was running*, any
322*6dbdd20aSAndroid Build Coastguard Workerallocations done before will not be shown.
323*6dbdd20aSAndroid Build Coastguard Worker
324*6dbdd20aSAndroid Build Coastguard Worker### {#capture-profile-native} Capturing the profile
325*6dbdd20aSAndroid Build Coastguard Worker
326*6dbdd20aSAndroid Build Coastguard WorkerUse the `tools/heap_profile` script to profile a process. If you are having
327*6dbdd20aSAndroid Build Coastguard Workertrouble make sure you are using the [latest version](
328*6dbdd20aSAndroid Build Coastguard Workerhttps://raw.githubusercontent.com/google/perfetto/main/tools/heap_profile).
329*6dbdd20aSAndroid Build Coastguard WorkerSee all the arguments using `tools/heap_profile -h`, or use the defaults
330*6dbdd20aSAndroid Build Coastguard Workerand just profile a process (e.g. `system_server`):
331*6dbdd20aSAndroid Build Coastguard Worker
332*6dbdd20aSAndroid Build Coastguard Worker```bash
333*6dbdd20aSAndroid Build Coastguard Worker$ tools/heap_profile -n system_server
334*6dbdd20aSAndroid Build Coastguard Worker
335*6dbdd20aSAndroid Build Coastguard WorkerProfiling active. Press Ctrl+C to terminate.
336*6dbdd20aSAndroid Build Coastguard WorkerYou may disconnect your device.
337*6dbdd20aSAndroid Build Coastguard Worker
338*6dbdd20aSAndroid Build Coastguard WorkerWrote profiles to /tmp/profile-1283e247-2170-4f92-8181-683763e17445 (symlink /tmp/heap_profile-latest)
339*6dbdd20aSAndroid Build Coastguard WorkerThese can be viewed using pprof. Googlers: head to pprof/ and upload them.
340*6dbdd20aSAndroid Build Coastguard Worker```
341*6dbdd20aSAndroid Build Coastguard Worker
342*6dbdd20aSAndroid Build Coastguard WorkerWhen you see *Profiling active*, play around with the phone a bit. When you
343*6dbdd20aSAndroid Build Coastguard Workerare done, press Ctrl-C to end the profile. For this tutorial, I opened a
344*6dbdd20aSAndroid Build Coastguard Workercouple of apps.
345*6dbdd20aSAndroid Build Coastguard Worker
346*6dbdd20aSAndroid Build Coastguard Worker### Viewing the data
347*6dbdd20aSAndroid Build Coastguard Worker
348*6dbdd20aSAndroid Build Coastguard WorkerThen upload the `raw-trace` file from the output directory to the
349*6dbdd20aSAndroid Build Coastguard Worker[Perfetto UI](https://ui.perfetto.dev) and click on diamond marker that
350*6dbdd20aSAndroid Build Coastguard Workershows.
351*6dbdd20aSAndroid Build Coastguard Worker
352*6dbdd20aSAndroid Build Coastguard Worker![Profile Diamond](/docs/images/profile-diamond.png)
353*6dbdd20aSAndroid Build Coastguard Worker
354*6dbdd20aSAndroid Build Coastguard WorkerThe tabs that are available are
355*6dbdd20aSAndroid Build Coastguard Worker
356*6dbdd20aSAndroid Build Coastguard Worker* **Unreleased malloc size**: how many bytes were allocated but not freed at
357*6dbdd20aSAndroid Build Coastguard Worker  this callstack the moment the dump was created.
358*6dbdd20aSAndroid Build Coastguard Worker* **Total malloc size**: how many bytes were allocated (including ones freed at
359*6dbdd20aSAndroid Build Coastguard Worker  the moment of the dump) at this callstack.
360*6dbdd20aSAndroid Build Coastguard Worker* **Unreleased malloc count**: how many allocations without matching frees were
361*6dbdd20aSAndroid Build Coastguard Worker  done at this callstack.
362*6dbdd20aSAndroid Build Coastguard Worker* **Total malloc count**: how many allocations (including ones with matching
363*6dbdd20aSAndroid Build Coastguard Worker  frees) were done at this callstack.
364*6dbdd20aSAndroid Build Coastguard Worker
365*6dbdd20aSAndroid Build Coastguard WorkerThe default view will show you all allocations that were done while the
366*6dbdd20aSAndroid Build Coastguard Workerprofile was running but that weren't freed (the **space** tab).
367*6dbdd20aSAndroid Build Coastguard Worker
368*6dbdd20aSAndroid Build Coastguard Worker![Native Flamegraph](/docs/images/native-heap-prof.png)
369*6dbdd20aSAndroid Build Coastguard Worker
370*6dbdd20aSAndroid Build Coastguard WorkerWe can see that a lot of memory gets allocated in paths through
371*6dbdd20aSAndroid Build Coastguard Worker`AssetManager.applyStyle`. To get the total memory that was allocated
372*6dbdd20aSAndroid Build Coastguard Workerthis way, we can enter "applyStyle" into the Focus textbox. This will only
373*6dbdd20aSAndroid Build Coastguard Workershow callstacks where some frame matches "applyStyle".
374*6dbdd20aSAndroid Build Coastguard Worker
375*6dbdd20aSAndroid Build Coastguard Worker![Native Flamegraph with Focus](/docs/images/native-heap-prof-focus.png)
376*6dbdd20aSAndroid Build Coastguard Worker
377*6dbdd20aSAndroid Build Coastguard WorkerFrom this we have a clear idea where in the code we have to look. From the
378*6dbdd20aSAndroid Build Coastguard Workercode we can see how that memory is being used and if we actually need all of
379*6dbdd20aSAndroid Build Coastguard Workerit.
380*6dbdd20aSAndroid Build Coastguard Worker
381*6dbdd20aSAndroid Build Coastguard Worker## {#java-hprof} Analyzing the Java Heap
382*6dbdd20aSAndroid Build Coastguard Worker
383*6dbdd20aSAndroid Build Coastguard Worker**Java Heap Dumps require Android 11.**
384*6dbdd20aSAndroid Build Coastguard Worker
385*6dbdd20aSAndroid Build Coastguard WorkerNOTE: For detailed instructions about capturing Java heap dumps and
386*6dbdd20aSAndroid Build Coastguard Worker      troubleshooting see the [Data sources > Java heap dumps](
387*6dbdd20aSAndroid Build Coastguard Worker      /docs/data-sources/java-heap-profiler.md) page.
388*6dbdd20aSAndroid Build Coastguard Worker
389*6dbdd20aSAndroid Build Coastguard Worker### {#capture-profile-java} Dumping the java heap
390*6dbdd20aSAndroid Build Coastguard WorkerWe can get a snapshot of the graph of all the Java objects that constitute the
391*6dbdd20aSAndroid Build Coastguard WorkerJava heap. We use the `tools/java_heap_dump` script. If you are having trouble
392*6dbdd20aSAndroid Build Coastguard Workermake sure you are using the [latest version](
393*6dbdd20aSAndroid Build Coastguard Workerhttps://raw.githubusercontent.com/google/perfetto/main/tools/java_heap_dump).
394*6dbdd20aSAndroid Build Coastguard Worker
395*6dbdd20aSAndroid Build Coastguard Worker```bash
396*6dbdd20aSAndroid Build Coastguard Worker$ tools/java_heap_dump -n com.android.systemui
397*6dbdd20aSAndroid Build Coastguard Worker
398*6dbdd20aSAndroid Build Coastguard WorkerDumping Java Heap.
399*6dbdd20aSAndroid Build Coastguard WorkerWrote profile to /tmp/tmpup3QrQprofile
400*6dbdd20aSAndroid Build Coastguard WorkerThis can be viewed using https://ui.perfetto.dev.
401*6dbdd20aSAndroid Build Coastguard Worker```
402*6dbdd20aSAndroid Build Coastguard Worker
403*6dbdd20aSAndroid Build Coastguard Worker### Viewing the Data
404*6dbdd20aSAndroid Build Coastguard Worker
405*6dbdd20aSAndroid Build Coastguard WorkerUpload the trace to the [Perfetto UI](https://ui.perfetto.dev) and click on
406*6dbdd20aSAndroid Build Coastguard Workerdiamond marker that shows.
407*6dbdd20aSAndroid Build Coastguard Worker
408*6dbdd20aSAndroid Build Coastguard Worker![Profile Diamond](/docs/images/profile-diamond.png)
409*6dbdd20aSAndroid Build Coastguard Worker
410*6dbdd20aSAndroid Build Coastguard WorkerThis will present a set of flamegraph views as explained below.
411*6dbdd20aSAndroid Build Coastguard Worker
412*6dbdd20aSAndroid Build Coastguard Worker#### "Size" and "Objects" tabs
413*6dbdd20aSAndroid Build Coastguard Worker
414*6dbdd20aSAndroid Build Coastguard Worker![Java Flamegraph: Size](/docs/images/java-heap-graph.png)
415*6dbdd20aSAndroid Build Coastguard Worker
416*6dbdd20aSAndroid Build Coastguard WorkerThese views show the memory attributed to the shortest path to a
417*6dbdd20aSAndroid Build Coastguard Workergarbage-collection root. In general an object is reachable by many paths, we
418*6dbdd20aSAndroid Build Coastguard Workeronly show the shortest as that reduces the complexity of the data displayed and
419*6dbdd20aSAndroid Build Coastguard Workeris generally the highest-signal. The rightmost `[merged]` stacks is the sum of
420*6dbdd20aSAndroid Build Coastguard Workerall objects that are too small to be displayed.
421*6dbdd20aSAndroid Build Coastguard Worker
422*6dbdd20aSAndroid Build Coastguard Worker* **Size**: how many bytes are retained via this path to the GC root.
423*6dbdd20aSAndroid Build Coastguard Worker* **Objects**: how many objects are retained via this path to the GC root.
424*6dbdd20aSAndroid Build Coastguard Worker
425*6dbdd20aSAndroid Build Coastguard WorkerIf we want to only see callstacks that have a frame that contains some string,
426*6dbdd20aSAndroid Build Coastguard Workerwe can use the Focus feature. If we want to know all allocations that have to
427*6dbdd20aSAndroid Build Coastguard Workerdo with notifications, we can put "notification" in the Focus box.
428*6dbdd20aSAndroid Build Coastguard Worker
429*6dbdd20aSAndroid Build Coastguard WorkerAs with native heap profiles, if we want to focus on some specific aspect of the
430*6dbdd20aSAndroid Build Coastguard Workergraph, we can filter by the names of the classes. If we wanted to see everything
431*6dbdd20aSAndroid Build Coastguard Workerthat could be caused by notifications, we can put "notification" in the Focus box.
432*6dbdd20aSAndroid Build Coastguard Worker
433*6dbdd20aSAndroid Build Coastguard Worker![Java Flamegraph with Focus](/docs/images/java-heap-graph-focus.png)
434*6dbdd20aSAndroid Build Coastguard Worker
435*6dbdd20aSAndroid Build Coastguard WorkerWe aggregate the paths per class name, so if there are multiple objects of the
436*6dbdd20aSAndroid Build Coastguard Workersame type retained by a `java.lang.Object[]`, we will show one element as its
437*6dbdd20aSAndroid Build Coastguard Workerchild, as you can see in the leftmost stack above. This also applies to the
438*6dbdd20aSAndroid Build Coastguard Workerdominator tree paths as described below.
439*6dbdd20aSAndroid Build Coastguard Worker
440*6dbdd20aSAndroid Build Coastguard Worker#### "Dominated Size" and "Dominated Objects" tabs
441*6dbdd20aSAndroid Build Coastguard Worker
442*6dbdd20aSAndroid Build Coastguard Worker![Java Flamegraph: Dominated Size](/docs/images/java-heap-graph-dominated-size.png)
443*6dbdd20aSAndroid Build Coastguard Worker
444*6dbdd20aSAndroid Build Coastguard WorkerAnother way to present the heap graph as a flamegraph (a tree) is to show its
445*6dbdd20aSAndroid Build Coastguard Worker[dominator tree](/docs/analysis/stdlib-docs.autogen#memory-heap_graph_dominator_tree).
446*6dbdd20aSAndroid Build Coastguard WorkerIn a heap graph, an object `a` dominates an object `b` if `b` is reachable from
447*6dbdd20aSAndroid Build Coastguard Workerthe root only via paths that go through `a`. The dominators of an object form a
448*6dbdd20aSAndroid Build Coastguard Workerchain from the root and the object is exclusvely retained by all objects on this
449*6dbdd20aSAndroid Build Coastguard Workerchain. For all reachable objects in the graph those chains form a tree, i.e. the
450*6dbdd20aSAndroid Build Coastguard Workerdominator tree.
451*6dbdd20aSAndroid Build Coastguard Worker
452*6dbdd20aSAndroid Build Coastguard WorkerWe aggregate the tree paths per class name, and each element (tree node)
453*6dbdd20aSAndroid Build Coastguard Workerrepresents a set of objects that have the same class name and position in the
454*6dbdd20aSAndroid Build Coastguard Workerdominator tree.
455*6dbdd20aSAndroid Build Coastguard Worker
456*6dbdd20aSAndroid Build Coastguard Worker* **Dominated Size**: how many bytes are exclusively retained by the objects in
457*6dbdd20aSAndroid Build Coastguard Workera node.
458*6dbdd20aSAndroid Build Coastguard Worker* **Dominated Objects**: how many objects are exclusively retained by the
459*6dbdd20aSAndroid Build Coastguard Workerobjects in a node.
460