Saat Anda perlu menyelidiki penggunaan memori, mulailah dengan alat penilaian tingkat tinggi untuk mengidentifikasi kategori memori yang paling signifikan.
dumpsys meminfo
Cara paling umum untuk mendapatkan ringkasan penggunaan memori aplikasi adalah
dumpsys meminfo. Untuk melihat perincian mendetail termasuk semua pemetaan memori, sebaiknya
sertakan flag -a:
adb shell dumpsys meminfo -a <package_name_or_pid>
Berikut adalah contoh output dari aplikasi yang mengalami tekanan memori (perhatikan SwapPss yang tinggi):
** MEMINFO in pid 4562 [com.android.memorylab] **
Pss Private Private SwapPss Rss Heap Heap Heap
Total Dirty Clean Dirty Total Size Alloc Free
------ ------ ------ ------ ------ ------ ------ ------
Native Heap 394 268 64 17440 4264 29416 18128 8040
Dalvik Heap 165 8 0 672 8196 40949 32757 8192
Dalvik Other 47 28 0 604 1132
Stack 112 108 4 312 120
...
TOTAL 33197 580 788 21920 167776 70365 50885 16232
App Summary
Pss(KB) Rss(KB)
------ ------
Java Heap: 12 32608
Native Heap: 268 4264
Code: 724 125672
Stack: 108 120
Graphics: 0 0
Private Other: 256
System: 31829
Unknown: 5112
TOTAL PSS: 33197 TOTAL RSS: 167776 TOTAL SWAP PSS: 21920
Objects
Views: 15 ViewRootImpl: 1
AppContexts: 5 Activities: 1
...
Menafsirkan data
- Pss Total: Proportional Set Size. Ini adalah jumlah
Private DirtyPrivate Clean+ bagian memori yang adil dari proses Anda yang dibagikan ke proses lain (seperti boot image Zygote). Ini adalah metrik terbaik untuk "seberapa banyak memori yang digunakan aplikasi ini".
- Private Dirty: Ini adalah RAM yang hanya digunakan oleh proses Anda dan telah dimodifikasi (atau merupakan memori anonim). Ini adalah angka paling penting untuk menemukan kebocoran karena memori ini tidak dapat dihapus.
- Private Clean: RAM yang hanya digunakan oleh proses Anda, tetapi merupakan salinan file yang tidak dimodifikasi di penyimpanan (seperti file DEX). Aplikasi dapat dihentikan oleh OS jika memori hampir habis.
- SwapPss: Memori yang telah dikompresi dan di-swap ke ZRAM. Hal ini dapat
terjadi karena sistem mengalami tekanan memori atau karena
Android Runtime telah mengidentifikasi proses latar belakang yang akan dipadatkan (memindahkan
halaman yang tidak digunakan atau tidak aktif ke ZRAM). Dalam contoh
dumpsys, hampir semuaNative HeapdanDalvik Heaptelah dipindahkan ke ZRAM.
- Ringkasan Aplikasi: Kategorisasi tingkat lebih tinggi yang menggabungkan baris mendetail ke dalam bucket yang dapat dipahami.
- Objek: Berguna untuk melacak instance
ActivitiesdanViewRootImplyang bocor. Jika Anda keluar dari aplikasi dan memaksa GC, jumlahActivitiesakan kembali ke 0.
Bagian anggaran memori
Di Android 18 dan yang lebih tinggi, dumpsys meminfo juga mencetak bagian Memory Budget
saat membuang satu aplikasi. Bagian ini membaca statistik
memcg dari proses dan seluruh aplikasi (paket), sehingga
Anda tidak perlu menemukan file cgroup sendiri. Berikut adalah bagian dari
aplikasi contoh MemoryLab di latar depan, setelah tiga ketukan Allocate Java
Memory (10MB):
Memory Budget
Process(KB) Package(KB)
----------- -----------
Current Usage: 83820 87976
Limit: none 4718592
Limit Source: none MemoryLimiter
Peak Usage: 85136 89292
Swap Used: 0 0
Usage Breakdown
Anonymous: 81700 81700
File: 96 4200
File Mapped: 16 616
Shared Memory: 16 16
Kernel: 1580 1632
Page Tables: 640 640
Slab: 439 458
Pressure & Reclaim
Throttle Events: 0 0
Refaults (Anon): 0 0
Refaults (File): 0 0
- Penggunaan Saat Ini: Memori yang dibebankan ke memcg (
memory.current). Ini adalah angka yang dibatasi oleh anggaran memori. Dalam contoh, jumlahnya meningkat sekitar 36.700 KB setelah tiga alokasi Java 10 MB, sejalan dengan TOTAL PSS. Total paket lebih tinggi daripada total proses, bahkan untuk aplikasi proses tunggal saat halaman file yang di-cache dari operasi sebelumnya belum diklaim kembali. - Limit: Batas klaim kembali (
memory.high) yang berlaku saat ini, ataunonejika tidak ada. Dalam contoh, paket memiliki batas memori sistem dan prosesnya tidak memiliki batasnya sendiri. - Sumber Batas: Sumber batas.
AndroidManifestadalah<memory-budget>yang dideklarasikan dalam manifes aplikasi,MemoryBudgetManageradalah anggaran yang ditetapkan aplikasi pada waktu proses,MemoryLimiteradalah batas memori sistem, danam memory-limiteradalah penggantian manual yang ditetapkan denganadb. - Penggunaan Puncak: Tagihan tertinggi sejak memcg dibuat
(
memory.peak). Ini menunjukkanN/Apada kernel yang tidak mendukungnya. - Swap Digunakan: Memori yang dikompresi ke ZRAM (
memory.swap.current). - Perincian Penggunaan: Kolom utama
memory.stat, seperti memori anonim dan yang didukung file. - Tekanan & Klaim Kembali: Peristiwa Throttle menghitung berapa kali memcg
melampaui batas
memory.high-nya. Refault menghitung halaman yang ditukar atau dikeluarkan, lalu diperlukan lagi. Jika angka ini meningkat saat Anda menggunakan aplikasi, batasnya lebih ketat daripada set kerja aplikasi.
Dengan flag -a atau -v, bagian ini juga mencantumkan setiap penghitung mentah dari
memory.stat dan memory.events.
Latihan praktik: triase cepat dengan meminfo
Latihan ini menunjukkan cara berbagai jenis alokasi muncul di meminfo.
Luncurkan aplikasi:
adb shell am start -W -n com.android.memorylab/.MainActivityMemeriksa memori dasar pengukuran:
adb shell dumpsys meminfo -s com.android.memorylab(Flag
-smemberikan ringkasan singkat dan padat tentang kategori memori).Alokasikan Memori Java: Ketuk tombol Alokasikan Memori Java (10 MB) 3 kali di aplikasi.
Amati perubahannya: Jalankan
meminfo -slagi. Anda akan melihat nilai Java Heap meningkat sekitar 30.000 KB (30 MB).Allocate Native Memory: Ketuk tombol Allocate Native Memory (1GB Incompressible) sekali.
Amati perubahannya: Jalankan
meminfo -slagi. Nilai Native Heap seharusnya sekarang menunjukkan peningkatan yang sangat besar (~1.000.000 KB).Bandingkan dengan memcg (Android 18 dan yang lebih baru): Lihat bagian Memory Budget di akhir output
meminfo -s. Penggunaan Saat Ini bertambah seiring dengan TOTAL PSS setelah setiap alokasi, karena alokasi Java dan native ditagih ke memcg aplikasi.
Tampilan global
Untuk melihat penggunaan memori di seluruh sistem, jalankan:
adb shell dumpsys meminfo
Perintah ini memberikan ringkasan penggunaan RAM, termasuk total RAM, RAM kosong, dan daftar proses yang diurutkan berdasarkan PSS.
Metrik sistem utama
- ZRAM: Swap terkompresi di RAM.
- DMA-BUF: Buffer memori bersama dan grafis. Versi Android modern menggunakan
DMA-BUF secara ekstensif untuk rendering UI. Jika total
DMA-BUFsangat tinggi, selidiki proses yang menggunakan banyak grafis menggunakan/sys/kernel/debug/dma_buf/bufinfo. - RAM yang hilang: Memori yang tidak diperhitungkan oleh kernel atau proses apa pun (misalnya, region yang dicadangkan hardware).
Statistik memcg
Setiap proses aplikasi memiliki grup kontrol memori (memcg) sendiri, dan kernel terus menjalankan total memori yang dibebankan kepadanya (lihat memcg untuk mengetahui perbedaan penghitungan ini dari RSS dan PSS). Membaca file ini tidak memerlukan banyak biaya dan tidak mengganggu aplikasi, sehingga Anda dapat mengambil sampelnya setiap detik saat menjalankan alur pengguna.
Cari jalur memcg proses dari baris 0:: dari /proc/<PID>/cgroup,
bukan membuat jalur sendiri, karena tata letak cgroup dapat berbeda
di antara perangkat. Teruskan setiap perintah perangkat ke adb shell sebagai string yang dikutip tunggal
sehingga shell perangkat melihat tanda kutip:
PID=$(adb shell pidof -s <package_name>)
CG=/sys/fs/cgroup$(adb shell "sed -n 's/^0:://p' /proc/$PID/cgroup")
adb shell "cat $CG/memory.current $CG/memory.swap.current"
adb shell "grep -E '^(anon|file|workingset_refault_.*) ' $CG/memory.stat"
File kuncinya adalah:
memory.current: Memori yang dibebankan ke proses, dalam byte. Ini adalah angka yang dibatasi oleh anggaran memori.memory.swap.current: Memori yang dikompresi ke ZRAM, dalam byte.memory.stat: Perincian biaya, dalam byte untuk ukuran.anonadalah memori anonim, seperti heap Java dan native.fileadalah cache halaman yang didukung file, seperti kode dan resource.workingset_refault_anondanworkingset_refault_filemenghitung halaman yang ditukar atau dikeluarkan, lalu diperlukan lagi. Jumlah refault yang meningkat berarti proses tersebut kekurangan memori.memory.events: Jumlah peristiwa batas memori.highmenghitung berapa kali proses dibatasi karena melebihi batasmemory.high.
Direktori induk memcg proses adalah milik seluruh aplikasi (UID-nya). Filenya mencakup memori semua proses aplikasi yang berjalan, ditambah halaman file yang di-cache yang tersisa dari proses aplikasi sebelumnya yang telah keluar dan belum diklaim kembali:
adb shell "cat $CG/../memory.current"
Jika Anda mendapatkan error izin, jalankan adb root dan coba lagi. Beberapa perangkat hanya
memungkinkan Anda membaca file ini sebagai root.
Untuk panduan terpandu tentang file ini dengan aplikasi contoh MemoryLab, lihat Latihan praktik: menjelajahi memcg.
showmap
Untuk perincian yang jauh lebih mendetail tentang pemetaan memori proses, gunakan
showmap. Alat ini membaca dari /proc/<pid>/smaps.
adb shell showmap <pid>
showmap mencantumkan setiap peta memori dalam proses. Pemetaan kunci yang perlu diperhatikan
antara lain:
[anon:scudo:primary]atau[anon:libc_malloc]: Heap native. Versi Android modern menggunakan alokator Scudo.*.art: Image heap Java (misalnya, boot image).[anon:dalvik-main space]: Heap Java utama.*.so: Pustaka bersama.*.{oat,dex,odex,vdex}: Kode DEX yang dikompilasi.
Anda dapat mengurutkan output untuk menemukan konsumen memori pribadi terbesar:
# Sort by private clean + private dirty memory
adb shell showmap <pid> | awk '{print $6+$7, $0}' | sort -rn | head -n 10
Contoh output:
virtual shared shared private private Anon Shmem File Shared Private
size RSS PSS clean dirty clean dirty swap swapPSS HugePages PmdMapped PmdMapped Hugetlb Hugetlb Locked # object
-------- -------- -------- -------- -------- -------- -------- -------- -------- --------- --------- --------- -------- -------- -------- ---- ------------------------------
2776 18176 5784 2823 0 3008 308 2468 4700 4700 0 0 0 0 0 0 47 [anon:scudo:primary]
560 952 876 657 316 0 560 0 12 12 0 0 0 0 0 0 8 /data/app/.../base.apk
448 393216 448 448 0 0 0 448 0 0 0 0 0 0 0 0 2 [anon:dalvik-main space]
...
Latihan praktik: pembahasan mendalam dengan showmap
Pelajari cara mengidentifikasi pemetaan memori tertentu dan membedakan antara memori bersih dan kotor.
- Mmap Clean Memory: Ketuk tombol Mmap Clean Anon Memory (10MB) di aplikasi MemoryLab sekali.
Mendapatkan ID Proses: UI aplikasi menampilkan PID-nya. Anda juga dapat menemukannya dengan perintah ini:
adb shell pidof com.android.memorylabMemeriksa dengan showmap:
# Replace <PID> with the actual process ID from the previous step adb shell showmap <PID> | grep "memorylab-clean"Identifikasi pemetaan: Anda akan melihat pemetaan anonim berlabel
[anon:memorylab-clean]dengan ukuran virtual tepat 10.240 KB. Perhatikan bahwa nilai private dirty untuk peta ini kemungkinan adalah 0. Ini adalah memori anonim "bersih" karena kita menggunakanmmapuntuk mencadangkan ruang virtual, tetapi belum menulis ke dalamnya (sehingga tidak ada RAM fisik yang benar-benar digunakan).Perbandingan Heap Native: Bandingkan ini dengan pemetaan
[anon:scudo:primary]yang akan muncul dishowmapjika Anda menjalankannya setelah langkah 5 latihanmeminfo. Karena alokasi native 1 GB tersebut sebenarnya menulis ke setiap halaman, halaman tersebut "dirty" dan akan muncul secara signifikan di kolom private dirty.Tips Pro (Objek Besar): Perhatikan alokasi Java Heap dari latihan
meminfo. Karena merupakan array byte 10 MB, array tersebut kemungkinan muncul dishowmapsebagai[anon:dalvik-free list large object space]. Android Runtime (ART) menempatkan objek yang lebih besar dari 12 KB ke dalam Large Object Space (LOS) terpisah untuk menghindari fragmentasi di heap utama.
procstats
Meskipun meminfo memberikan snapshot pada suatu waktu, procstats memberikan data
historis dengan mengambil sampel status dan penggunaan memori secara berkala dari semua aplikasi
yang berjalan. Ini adalah alat utama yang digunakan untuk pemantauan kesehatan memori jangka panjang
dan yang mendorong pelaporan penggunaan memori di Setelan Android.
# View stats for the last 3 hours
adb shell dumpsys procstats --hours 3
Memahami status
Output procstats bisa sangat banyak. Bagian yang paling penting adalah
metrik dalam tanda kurung di samping setiap status proses:
Top: 100% (54MB-64MB-67MB / 49MB-58MB-61MB / 110MB-120MB-130MB over 4)
Formatnya adalah: (% waktu dalam status) (minPss-avgPss-maxPss / minUss-avgUss-maxUss / minRss-avgRss-maxRss di atas sampel)
- Pss (Proportional Set Size): Memori bersama dibagi secara proporsional di antara proses.
- Uss (Unique Set Size): Memori yang hanya digunakan oleh proses ini (setara dengan Private Clean + Private Dirty).
- Rss (Resident Set Size): Total memori fisik yang digunakan, termasuk semua halaman bersama (cenderung dihitung berlebihan).
Mengapa hal ini penting:
- Aplikasi Stabil: min/rata-rata/maks berdekatan.
- Kebocoran Memori: nilai maksimum jauh lebih tinggi daripada nilai minimum, dan nilai rata-rata meningkat seiring waktu seiring bertambahnya jumlah sampel.
- Penggunaan yang Berfluktuasi: nilai maksimum jauh lebih tinggi daripada rata-rata, yang menunjukkan operasi berat sementara (seperti pemrosesan gambar) yang dapat menyebabkan OOM jika terjadi pada waktu yang salah.
Status proses
procstats melacak aplikasi di beberapa negara bagian (sering kali disingkat):
- Persist: Proses sistem penting yang selalu berjalan.
- Atas: Aplikasi saat ini berada di latar depan dan terlihat oleh pengguna.
- ImpFg (Latar Depan Penting): Proses latar belakang penting (seperti IME) atau aplikasi dengan layanan latar depan.
- ImpBg (Latar Belakang Penting): Proses latar belakang yang dianggap penting bagi sistem.
- Fgs / BFgs: Layanan Latar Depan atau Layanan Latar Depan Terikat.
- Service / ServRst: Layanan latar belakang atau layanan yang sedang dimulai ulang.
- Cached / LastAct: Aplikasi yang di-cache di latar belakang untuk memulai ulang dengan cepat. Proses ini aman untuk dihentikan oleh sistem.
Status memori perangkat dan statistik waktu proses
procstats juga melacak berapa lama seluruh perangkat mengalami tekanan memori. Cari bagian Run time Stats:
Run time Stats:
SOff/Norm: +1h10m15s
SOn/Norm: +15m20s
Low: +2m10s
Crit: +45s
- SOff / SOn: Layar Nonaktif vs. Layar Aktif.
- Norm / Mod / Low / Crit: Tingkat tekanan memori (Normal, Moderate, Low, Critical).
Jika perangkat menghabiskan banyak waktu dalam status Low atau Crit, perangkat akan terasa lambat karena kernel secara agresif mengklaim kembali memori dan Low Memory Killer (LMK) mulai menghentikan proses latar belakang. Kemudian, Anda dapat melihat statistik per paket untuk mengetahui aplikasi mana yang memiliki penggunaan memori tinggi, khususnya saat perangkat berada dalam status tertekan ini.