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 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 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 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 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 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 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 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 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 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