Halaman ini membahas interaksi antara kswapd dan lmkd di Android,
yang menunjukkan cara keduanya bekerja sama untuk mengelola tekanan memori.
Latar belakang
Android menggunakan dua mekanisme utama untuk mengklaim kembali memori saat sistem kehabisan memori:
kswapd: Daemon kernel Linux standar yang mengklaim kembali halaman dengan mengeluarkan halaman yang didukung file bersih atau menukar halaman anonim ke ZRAM.lmkd: Daemon Low Memory Killer userspace Android. Jikakswapdtidak dapat memenuhi permintaan memori dan tekanan sistem meningkat (seperti yang ditunjukkan oleh PSI),lmkdakan menghentikan proses untuk mengosongkan bagian memori yang lebih besar.
kswapd dan lmkd adalah dua sistem klaim kembali memori yang saling melengkapi. Keduanya berfungsi untuk
mencapai sasaran yang sama (membuat memori kosong), tetapi dengan cara yang berbeda. Untuk membandingkan
dan membedakan:
- Dapat Dipulihkan vs Merusak:
kswapdmenghapus halaman memori yang dapat dibaca kembali dari penyimpanan, atau menukar halaman memori ke partisi memori atau penyimpanan lain yang dapat dibaca kembali sesuai permintaan.lmkdmenghentikan proses, yang menghancurkan status non-volatil. - Bandwidth Reclaim:
kswapdmenggunakan lebih banyak CPU untuk mengklaim kembali sejumlah memori kosong tertentu daripadalmkd, dan memerlukan waktu lebih lama untuk mengklaim kembali memori tersebut.lmkddapat mengklaim kembali memori dalam jumlah besar dalam waktu singkat dengan upaya yang relatif sedikit. Perlu diingat bahwa pada perangkat seluler, upaya CPU tidak hanya memengaruhi latensi, tetapi juga daya baterai.
Bucket skor OOM
Android menetapkan penyesuaian skor Out-Of-Memory (OOM) (oom_score_adj) ke
proses berdasarkan kepentingannya bagi pengguna. Proses dengan skor lebih tinggi
akan dihentikan terlebih dahulu.
Bucket umum mencakup:
- Cached (Skor >= 900): Proses yang saat ini tidak diperlukan, disimpan untuk memulai ulang lebih cepat.
- Layanan (Skor 500): Proses yang menghosting layanan yang dimulai.
- Layanan Latar Depan (Skor 200): Proses yang menghosting layanan latar depan.
- Latar depan (Skor 0): Aplikasi yang saat ini digunakan untuk berinteraksi oleh pengguna.
Pembahasan mendalam: Pemicuan PSI dan LMKD
Apa itu PSI?
Pressure Stall Information (PSI) adalah fitur kernel Linux yang menyediakan cara kanonis untuk mengukur kekurangan resource. PSI melacak waktu penundaan tugas karena kekurangan CPU, memori, dan I/O.
PSI Memori: "some" versus "full"
PSI memori secara khusus melacak penundaan yang disebabkan oleh kekurangan memori (misalnya, menunggu reklamasi halaman atau kesalahan ulang). Metrik ini menyediakan dua metrik:
some: Persentase waktu saat setidaknya satu tugas terhenti di memori. Hal ini menunjukkan bahwa kekurangan memori memengaruhi performa, tetapi beberapa pekerjaan masih berjalan.full: Persentase waktu saat semua tugas yang tidak ada aktivitas terhenti secara bersamaan. Hal ini menunjukkan status kritis saat sistem sepenuhnya diblokir saat menunggu memori.
Cara PSI memicu LMKD
Daemon lmkd userspace mendaftar ke kernel untuk menerima notifikasi
saat nilai minimum PSI terlampaui (dengan memantau /proc/pressure/memory). Saat
sistem mengalami tekanan memori yang tinggi (misalnya, stall full melebihi
durasi yang dikonfigurasi), kernel akan mengaktifkan lmkd. lmkd kemudian mengevaluasi
status sistem dan memutuskan apakah akan menghentikan proses, dan proses mana, berdasarkan
skor dan ukuran OOM-nya.
Penyesuaian LMKD
Perilaku LMKD dapat disesuaikan menggunakan properti sistem.
Menemukan nilai penyesuaian di perangkat
Anda dapat menemukan nilai penyesuaian LMKD saat ini di perangkat terhubung dengan menjalankan:
adb shell getprop | grep lmk
Properti LMKD umum
Berikut adalah beberapa properti utama yang digunakan untuk menyesuaikan LMKD (lihat Dokumentasi Android untuk mengetahui daftar lengkapnya):
ro.lmk.use_psi: Tetapkan ketrueuntuk menggunakan monitor PSI untuk deteksi tekanan memori (default di Android 10+).ro.lmk.psi_partial_stall_ms: Nilai minimum untuk durasi stallsome(parsial) dalam milidetik untuk memicu penghentian (default 70 md pada perangkat normal, 200 md pada perangkat dengan RAM rendah).ro.lmk.psi_complete_stall_ms: Nilai minimum untuk durasi stallfulldalam milidetik untuk memicu penghentian (default 700 md).ro.lmk.kill_heaviest_task: Jikatrue, LMKD akan menghentikan proses yang menggunakan memori terbanyak di antara kandidat dalam bucket OOM yang sama.
Nilai penyesuaian yang relevan di perangkat pengujian (Google Pixel 8 Pro)
(Catatan: Default umum untuk perangkat kelas atas yang menjalankan Android 15)
ro.lmk.use_psi:truero.lmk.psi_partial_stall_ms:70(standar)ro.lmk.psi_complete_stall_ms:700(standar)ro.lmk.kill_heaviest_task:true
Verifikasi ZRAM dan swap
Kapasitas ZRAM sangat memengaruhi seberapa cepat swap terisi dan memicu penghentian LMKD. Anda dapat memeriksa status ZRAM dan swap di perangkat menggunakan perintah berikut:
# Check ZRAM sizing and usage
adb shell free -m
# Check swap partition details
adb shell cat /proc/swaps
Latihan praktis: memicu kswapd dan lmkd
Dalam latihan ini, Anda akan menggunakan aplikasi contoh KswapdLmkdLab untuk membuat
proses di bucket OOM yang berbeda, lalu menggunakan memori dalam proses utama
untuk memicu kswapd dan lmkd.
Aplikasi dikonfigurasi untuk otomatis menghasilkan subproses dan mengalokasikan memori agar menjadi target yang menarik bagi LMKD.
1. Membuat subproses
Aplikasi akan otomatis memunculkan subproses berikut saat diluncurkan:
- Proses yang Di-cache (oom_score_adj >= 900)
- Proses Layanan (oom_score_adj 500)
- Proses Layanan Latar Depan (oom_score_adj 200)
Verifikasi proses dan skor OOM-nya menggunakan ADB:
adb shell dumpsys activity processes | grep com.android.kswapdlmkdlab
Contoh Cuplikan Output:
Proc # 0: fg T/A/TOP LCMNFUATI t: 0 18959:com.android.kswapdlmkdlab/u0a358 (top-activity)
Proc # 1: prcp b/ /FGS -------TI t: 0 19050:com.android.kswapdlmkdlab:foreground/u0a358 (fg-service)
Proc # 2: svc b/ /SVC -------TI t: 0 19077:com.android.kswapdlmkdlab:service/u0a358 (started-services)
Proc # 3: cch b/ /CACC -------TI t: 0 19014:com.android.kswapdlmkdlab:cached/u0a358 (cch-client-act)
Singkatan status proses sesuai dengan:
fg: Latar depan (skor OOM 0)prcp: Terlihat (Layanan Latar Depan, skor OOM 200)svc: Layanan yang Dimulai (skor OOM 500)cch: Proses yang Di-cache (skor OOM 900)
2. Memicu tekanan memori
Aplikasi akan otomatis mulai mengalokasikan memori dalam proses utama. Agar pengujian efektif pada perangkat dengan RAM tinggi, aplikasi juga memerintahkan subproses untuk mengalokasikan memori (misalnya, masing-masing 500 MB) agar menjadi target yang lebih baik untuk LMKD.
Memantau penghentian subproses
Aplikasi memantau penghentian subproses ini menggunakan
mekanisme IBinder.linkToDeath:
- Proses utama mengikat ke layanan dalam proses target menggunakan
bindService. - Setelah terhubung, class ini akan mendapatkan objek
IBinderyang mewakili layanan. - Fungsi ini mendaftarkan implementasi
IBinder.DeathRecipientdengan memanggillinkToDeathpada binder. - Saat proses target berhenti (misalnya, saat dihentikan oleh LMKD), sistem
akan memanggil metode
binderDied(), sehingga aplikasi dapat mencatat peristiwa penghentian secara asinkron.
Untuk mencegah binding ini meningkatkan prioritas proses target
(yang akan menggagalkan tujuan latihan), aplikasi menggunakan
flag Context.BIND_WAIVE_PRIORITY.
Cara kerja aplikasi contoh
Berikut screenshot aplikasi setelah uji coba selesai di Google Pixel 8 Pro (yang memiliki total RAM sekitar 12 GB).
Analisis rekaman aktivitas Perfetto
Untuk merekam interaksi, gunakan konfigurasi Perfetto berikut untuk merekam penjadwalan, penghitung memori, penghentian LMK, dan Pressure Stall Information (PSI).
Konfigurasi Perfetto
Rekam interaksi dengan menjalankan Perfetto dengan penjadwalan, penghitung memori, penghentian LMK, dan Pressure Stall Information (PSI):
adb shell perfetto -c - --txt -o /data/misc/perfetto-traces/kswapd_lmkd.perfetto-trace <<EOF
buffers: { size_kb: 131072 }
data_sources: {
config {
name: "linux.ftrace"
ftrace_config {
ftrace_events: "lowmemorykiller/lowmemory_kill"
ftrace_events: "vmscan/mm_vmscan_kswapd_wake"
ftrace_events: "vmscan/mm_vmscan_kswapd_sleep"
ftrace_events: "psi/psi_event"
}
}
}
duration_ms: 180000
EOF
Meninjau rekaman aktivitas
Screenshot berikut diambil dari rekaman aktivitas yang menunjukkan jangka waktu
sebelum proses :cached (paling dapat dihentikan) dihentikan, hingga
proses :foreground (paling tidak dapat dihentikan) dihentikan.
Anda dapat melihat bahwa MemFree sudah cukup rendah dan terus mengalami tekanan.
kswapd terus bekerja dan mengurangi tekanan dengan menghapus halaman mem.rss.file
dan memindahkan mem.rss.anon ke mem.swap dari semua proses kswapdlmkdlab (proses utama dan subproses), dan kemungkinan dari proses lain
yang tidak ditampilkan dalam screenshot ini. Pada saat yang sama, aplikasi kswapdlmkdlab
terus mengalokasikan memori, sehingga meningkatkan tekanan lebih cepat daripada yang dapat
diklaim kembali oleh kswapd.
Saat tekanan menjadi terlalu tinggi, seperti yang terlihat pada psi.mem yang tinggi selama
jangka waktu yang cukup, lmkd akan aktif dan menghentikan beberapa proses. Anda dapat melihat
bahwa lmkd mematuhi skor OOM, menghentikan kswapdlmkdlab:cached terlebih dahulu, lalu
:service, kemudian :foreground.
Tinjau linimasa peristiwa dan renungkan hal berikut:
- Cara
kswapddanlmkdsaling melengkapi:kswapdadalah yang pertama merespons tekanan memori, tetapilmkdmembantu saat bandwidth reclaimkswapdtidak memenuhi permintaan alokasi. - Tingkat memori yang dikosongkan: amati waktu CPU yang dihabiskan di
kswapddan memori yang diklaim kembali dengan menghapusmem.rss.fileatau menukarmem.rss.anonkemem.swap. Bandingkan ini dengan aktivitas singkat dilmkdyang menyebabkan sejumlah besar memori pribadi proses dirilis.
Kueri
Jalankan kueri ini di Perfetto UI (Query SQL) untuk mengekstrak data dari trace Anda.
1. Aktivitas kswapd
Untuk menemukan kapan daemon swap kernel aktif dan berjalan, jalankan:
SELECT ts, dur, state
FROM thread_state
JOIN thread USING (utid)
WHERE thread.name LIKE 'kswapd%'
AND state = 'Running'
LIMIT 5;
Contoh Output:
| ts | dur | state |
|---|---|---|
| 30317633052969 | 159180 | Berjalan |
| 30317633398347 | 3999186 | Berjalan |
| 30317638448111 | 1847941 | Berjalan |
| 30317641455354 | 1031006 | Berjalan |
| 30317643272615 | 888387 | Berjalan |
2. Penghentian LMKD
LMKD menulis penghentian proses akibat memori hampir habis ke tabel instant. Untuk mengkueri semua penghentian LMKD:
SELECT ts, name
FROM instant
WHERE name LIKE 'lmk,%'
ORDER BY ts ASC;
Format nama peristiwa adalah:
lmk,<pid>,<kill_reason>,<oom_score_adj>,<min_oom_score>,<max_thrashing>.
kill_reason: Bilangan bulat yang menunjukkan alasanlmkdmemutuskan untuk menghentikan proses (ditentukan dalamsystem/memory/lmkd/statslog.h):0:PRESSURE_AFTER_KILL1:NOT_RESPONDING2:LOW_SWAP_AND_THRASHING(Ruang swap ZRAM sangat rendah dan terjadi thrashing)3:LOW_MEM_AND_SWAP(Sistem kehabisan memori kosong dan swap ZRAM)4:LOW_MEM_AND_THRASHING5:DIRECT_RECL_AND_THRASHING6:LOW_MEM_AND_SWAP_UTIL7:LOW_FILECACHE_AFTER_THRASHING8:LOW_MEM9:DIRECT_RECL_STUCK
max_thrashing: Persentase thrashing halaman maksimum pada saat penghentian.
Contoh Output:
| ts | nama |
|---|---|
| 30326148679967 | lmk,2308,3,900,201,0 |
| 30330439763710 | lmk,2309,3,500,201,0 |
| 30334985999837 | lmk,2310,2,200,0,307 |
Visualisasi
Untuk memvisualisasikan data, Anda dapat menggunakan skrip gnuplot berikut untuk memetakan memori bebas sistem, aktivitas kswapd, penghentian lmkd, dan PSI pada satu deret waktu. Skrip ini mengasumsikan bahwa skrip dijalankan dari direktori teratas build Android.
Contoh plot output
Plot berikut dibuat menggunakan skrip sebelumnya dengan data sampel yang mewakili uji coba.
Penjelasan Plot:
Plot ini menggambarkan interaksi dinamis antara berbagai komponen manajemen memori selama uji ketahanan:
- Penurunan Memori Bebas: Saat aplikasi utama mengalokasikan memori, memori bebas sistem (garis ungu) terus menurun.
- Aktivasi kswapd: Saat memori bebas turun di bawah batas tertentu,
kswapdakan aktif (impuls biru) untuk mengklaim kembali memori dengan melakukan pertukaran ke ZRAM. Hal ini terlihat sebagai lonjakan yang terputus-putus. - Lonjakan PSI: Saat
kswapdkesulitan mengimbangi tingkat alokasi yang tinggi, thread mulai terhenti pada alokasi memori, sehingga menyebabkan PSI (Pressure Stall Information) (garis hijau) melonjak. - Penghentian LMKD: Saat PSI mencapai tingkat kritis (misalnya, melebihi
batas
ro.lmk.psi_complete_stall_mssecara konseptual) dan memori bebas sangat rendah,lmkdakan mengintervensi dengan menghentikan proses berprioritas rendah (impuls oranye pada waktu 30 dan 45) untuk mengosongkan sebagian besar memori. Perhatikan bahwa segera setelah penghentian, memori bebas meningkat dan PSI menurun, yang menunjukkan efektivitas penghentian dalam mengurangi tekanan. ________________________________________________________________________________
← Pengambilan kembali memori: penghapusan dan swap | ↑ Atas | Mengembalikan halaman memori ke OS →