Daemon pengelolaan memori

Android 17 dan yang lebih tinggi mendukung daemon pengelolaan memori (mmd), daemon sistem, yang menangani konfigurasi daemon, tunables, dan tugas pemeliharaan swap atau ZRAM yang sedang berlangsung.

Latar belakang

Sebelum diperkenalkannya mmd, konfigurasi ZRAM Android terfragmentasi dan menawarkan penyesuaian terbatas. mmd mengatasi hal ini dengan memusatkan pengelolaan ZRAM, memungkinkan logika konfigurasi yang lebih canggih dan menyederhanakan penambahan fitur baru dan peningkatan arsitektur. mmd juga menetapkan pemisahan masalah yang jelas antara proses system_server berbasis Java dan pengelolaan memori atau swap tingkat kernel.

Arsitektur dan pengelolaan ZRAM

Setelah penyelesaian booting (yaitu, saat sys.boot_completed=1), mmd_setup akan mencoba mengonfigurasi ZRAM dengan parameter yang ditentukan. Setelah penyiapan ZRAM selesai, sistem akan mengaktifkan layanan mmd yang menangani tugas pemeliharaan berkelanjutan.

Dengan project mmd, operasi pemeliharaan dimulai dari system_server dengan mengirim permintaan Binder ke mmd menggunakan antarmuka IMmd. mmd menangani tugas pemeliharaan untuk melakukan penulisan balik ZRAM, kompresi ulang, dan penulisan balik per proses berdasarkan mesin kebijakan internalnya sendiri. Penjadwalan dari ActivityManagerService dan kebijakan pemeliharaan ZRAM dapat dikonfigurasi menggunakan properti sistem.

Integrasi server sistem (system_server)

Proses system_server berbasis Java menentukan kapan mmd dipanggil. Proses ini memisahkan pembersihan pemeliharaan global dari pengoptimalan memori per aplikasi yang ditargetkan.

Pemeliharaan pasca-pemrosesan normal

Pemeliharaan ZRAM global didorong oleh ActivityManagerService menggunakan com.android.server.memory.ZramMaintenance.

zram-maintenance

Gambar 1. Alur penjadwalan pemeliharaan ZRAM.

  • Mesin penjadwalan: ZramMaintenance mendaftarkan tugas latar belakang berkala dengan JobScheduler Android.
  • Batasan tugas: Untuk mencegah ketersendatan UI latar depan atau pertentangan CPU, tugas dikonfigurasi secara eksplisit dengan setRequiresDeviceIdle(true) dan setRequiresBatteryNotLow(true).
  • Pemicuan binder: Saat penjadwal mengaktifkan onStartJob(), system_server memanggil mmd.doZramMaintenanceAsync(). Ini adalah panggilan Binder asinkron satu arah; system_server tidak memblokir saat menunggu pembersihan pemeliharaan selesai. mmd mengantrekan ini ke thread pekerja latar belakang untuk melakukan kompresi ulang dan penulisan kembali secara berurutan.

Penulisan balik per proses

Pengusiran memori per proses yang ditargetkan dikelola oleh ActivityManagerService menggunakan com.android.server.am.CachedAppOptimizer.

mmd-writeback

Gambar 2. Alur penulisan balik per proses mmd.

Saat proses bertransisi ke status cache latar belakang, ActivityManager melakukan pemadatan memori. Jika proses yang dihentikan karena memori rendah akan terlihat oleh pengguna, yaitu proses menghosting Aktivitas, dan jika penulisan balik per proses ZRAM akan membuat jejak memori proses mendekati nol, sistem akan mengikuti langkah-langkah berikut:

  1. Setelah pemadatan, CachedAppOptimizer memposting pesan yang tertunda (ZRAM_WRITEBACK_MSG) ke handler pemadatan internalnya (tertunda oleh mZramWritebackWaitSeconds).
  2. Saat penundaan berakhir, ActivityManager akan membuka deskriptor file proses aman pidfd.
  3. Server sistem memanggil mmd.asyncWritebackProcessZramMemory(pfd, callback).
  4. mmd mengeksekusi ioctl writeback per proses dan melaporkan kembali menggunakan IMmdProcessWritebackCallback. Jika berhasil, ActivityManager menandai rekaman proses (setIsZramWrittenBack(app, true)) untuk meningkatkan oom_score_adj proses dan mencatat metrik ke FrameworkStatsLog.ZRAM_WRITEBACK_EVENT.

Prefetch per proses

Saat pengguna meluncurkan ulang aplikasi yang sebelumnya di-cache (dibatalkan pembekuannya karena UNFREEZE_REASON_ACTIVITY), ActivityManager meminimalkan latensi peluncuran aplikasi yang disebabkan oleh kesalahan halaman utama dari penyimpanan pendukung:

  1. CachedAppOptimizer mencegat peristiwa pembatalan pembekuan dan memanggil prefetchZram(app).
  2. Server sistem mengirimkan pidfd aplikasi di seluruh Binder menggunakan mmd.asyncPrefetchProcessZramMemory(pfd). mmd mengeluarkan ioctl ZRAM_ANDROID_IOC_PROCESS_PREFETCH, yang menginstruksikan kernel untuk melakukan pengambilan data halaman yang ditukar kembali ke RAM secara asinkron saat thread UI utama aplikasi sedang diinisialisasi.

Ringkasan tugas pemeliharaan dan pasca-pemrosesan

Bagian ini menjelaskan operasi pemeliharaan latar belakang dan tugas pasca-pemrosesan yang dijalankan mmd untuk mengoptimalkan ruang swap dan memori sistem.

Pemeliharaan di mmd

Di mmd, pemeliharaan mengacu pada pembersihan pemeliharaan latar belakang terjadwal yang mengoptimalkan penggunaan ruang swap dan memori fisik tanpa memengaruhi performa latar depan pengguna aktif. Daripada melakukan pemindaian sinkron yang berkelanjutan (yang akan menyebabkan bangun CPU yang parah dan jank UI), pemeliharaan dilakukan secara asinkron:

  1. system_server secara berkala memicu doZramMaintenanceAsync() di seluruh Binder.

  2. mmd menempatkan permintaan pada antrean pekerjaan latar belakang LowPrioWorkItem::ZramMaintenance.

  3. Ada satu thread pekerja di mmd yang mengelola antrean prioritas tinggi dan antrean prioritas rendah. Item kerja berprioritas tinggi (seperti pengambilan data per proses) diproses terlebih dahulu dan dapat mendahului item kerja berprioritas rendah. Pemeliharaan dan penulisan ulang per proses beroperasi sebagai item kerja berprioritas rendah. Saat muncul, thread pekerja menjalankan dua operasi pemeliharaan utama secara berurutan:

    • Kompresi ulang ZRAM: Memindai halaman swap yang ada dan mengompresi ulang halaman yang tidak ada aktivitas menggunakan algoritma kompresi sekunder dengan rasio yang lebih tinggi, misalnya, zstd.

    • Penulisan ulang ZRAM: Memindai halaman yang tidak ada aktivitas dan menghapusnya sepenuhnya dari RAM ke penyimpanan flash pendukung perangkat loop dari file di /data.

Tugas pasca-pemrosesan di ZRAM

Dalam modul ZRAM kernel Linux dan arsitektur mmd, tugas pasca-pemrosesan adalah transformasi asinkron yang diterapkan ke halaman memori setelah halaman tersebut ditukar oleh jalur pemulihan standar kernel (kswapd atau pemadatan).

Saat halaman awalnya dikeluarkan, sistem memprioritaskan kecepatan: sistem menggunakan algoritma kompresi utama yang cepat (seperti lz4) dan menyimpan halaman yang dikompresi di RAM. Namun, seiring waktu, banyak halaman yang ditukar menjadi tidak aktif atau menganggur, misalnya, aplikasi yang di-cache di latar belakang yang tidak dilanjutkan selama berjam-jam. Membiarkan halaman dingin di ZRAM yang cepat dan dikompresi ringan tidak efisien.

Pipeline pasca-pemrosesan

mmd menerapkan siklus proses pasca-pemrosesan multi-tahap untuk mengoptimalkan halaman ini:

mmd-page-lifecycle

Gambar 3. siklus proses halaman mmd.

  1. Tahap 1: Penggantian awal (kompresi cepat): Memori pertama-tama direklamasi melalui kswapd atau pemadatan aplikasi. Biasanya, pemulihan pertama ini dilakukan menggunakan algoritma kompresi cepat seperti lz4 dan kontennya disimpan di RAM.

  2. Tahap 2: Penandaan tidak ada aktivitas (penuaan & pelacakan): Pelacakan tidak ada aktivitas mmd mengakses pelacakan memori kernel (CONFIG_ZRAM_TRACK_ENTRY_ACTIME) atau menggunakan penanda tidak ada aktivitas software-nya untuk melacak berapa lama halaman tidak disentuh.

  3. Tahap 3: Pemrosesan pasca 1 - kompresi ulang (pemulihan dalam memori): Halaman yang mencapai usia tidak ada aktivitas kompresi ulang (min_idle_seconds hingga max_idle_seconds) akan menjalani kompresi ulang. mmd menulis ke /sys/block/zram0/recompress untuk menginstruksikan kernel agar mendekompresi halaman lz4 dan mengompresi ulang menggunakan zstd. Tindakan ini akan merebut kembali RAM fisik tanpa menimbulkan keausan penulisan flash.

  4. Tahap 4: Pemrosesan pasca-2 - penulisan kembali (pengusiran ke penyimpanan flash): Jika tekanan memori berlanjut dan halaman mencapai usia tidak aktif penulisan kembali (biasanya 20 jam atau lebih), mmd memicu penulisan kembali. mmd menulis ke /sys/block/zram0/idle dan /sys/block/zram0/writeback untuk mengeluarkan halaman terkompresi sepenuhnya dari RAM ke penyimpanan flash pendukung.

Konfigurasi penyiapan ZRAM

mmd memuat dan memproses properti penyiapan ZRAM berikut:

Properti Gunakan Default
mmd.zram.enabled Apakah penyiapan ZRAM mmd diaktifkan. false
mmd.zram.num_devices Jumlah perangkat ZRAM yang akan dikonfigurasi. Untuk sejumlah N, perangkat zram0 hingga zram<N-1> harus ada sebelum sistem menyetel sys.boot_completed=1. Properti pada daftar perangkat per-ZRAM dapat dikonfigurasi berdasarkan per-perangkat. 1
mmd.zram.device_priority Nilai prioritas yang akan diteruskan saat memanggil swapon. Tidak ditetapkan
mmd.zram.comp_algorithm Algoritma kompresi ZRAM. Algoritma kompresi default kernel digunakan jika tidak ditentukan. Tidak ditetapkan
mmd.zram.size Ukuran perangkat ZRAM dalam byte, atau persentase ukuran RAM perangkat, misalnya, 75%. 50%
mmd.zram.writeback.enabled Apakah akan mengaktifkan penulisan ulang ZRAM atau tidak. false
mmd.zram.writeback.device_size Ukuran perangkat tulis balik dalam byte atau persentase partisi data. Ukuran perangkat sebenarnya dapat disesuaikan berdasarkan ruang yang tersedia di partisi data. 1073741824 (1 GiB)
mmd.zram.writeback.min_free_space_mib Ruang kosong minimum dalam MiB yang harus tersedia setelah perangkat penulisan balik disiapkan. 1536 (1,5 GiB)
mmd.zram.writeback.use_nr_tags_prop Saat true, menggunakan nilai di mmd.zram.writeback.nr_tags untuk mengonfigurasi kedalaman antrean perangkat loop yang mendukung penulisan balik ZRAM. Hal ini merupakan solusi untuk situasi saat kebijakan SELinux vendor tidak dapat dikonfigurasi untuk mengizinkan mmd membaca nr_tags secara langsung dari perangkat blok yang mendukung /data. false
mmd.zram.writeback.nr_tags Lihat mmd.zram.writeback.use_nr_tags_prop. Tidak ditetapkan
mmd.zram.recompression.enabled Apakah akan mengaktifkan fitur kompresi ulang ZRAM. false
mmd.zram.recompression.algorithm Algoritma kompresi ulang ZRAM sekunder. zstd

Properti perangkat per ZRAM

Jika mmd.zram.num_devices lebih besar dari satu, properti tertentu dapat dikonfigurasi secara opsional berdasarkan per perangkat ZRAM dengan menyetel properti ke nilai yang dipisahkan koma yang berisi tepat mmd.zram.num_devices elemen. Properti ini meliputi:

  • mmd.zram.size
  • mmd.zram.comp_algorithm
  • mmd.zram.device_priority
  • mmd.zram.recompression.enabled
  • mmd.zram.recompression.huge_idle.enabled
  • mmd.zram.recompression.idle.enabled
  • mmd.zram.recompression.huge.enabled
  • mmd.zram.recompression.threshold_bytes
  • mmd.zram.recompression.algorithm
  • mmd.zram.writeback.device_size
  • mmd.zram.writeback.huge_idle.enabled
  • mmd.zram.writeback.idle.enabled
  • mmd.zram.writeback.huge.enabled

Penghentian penyiapan ZRAM yang ada

Meskipun swapon_all masih tersedia di Android untuk menyiapkan ruang swap berbasis disk dan ZRAM, mmd adalah pendekatan yang lebih disukai untuk pengelolaan ZRAM agar konfigurasi lebih mudah dan fitur lanjutan seperti kompresi ulang ZRAM.

Jika penyiapan ZRAM mmd diaktifkan oleh mmd.zram.enabled:

  • Penyiapan ZRAM dalam implementasi swapon_all menjadi tidak berfungsi.
  • Konfigurasi ZRAM yang ada seperti config_zramWriteback dalam file overlay config.xml dan properti sistem penulisan ulang ro.zram.* diabaikan.

Penyesuaian pemeliharaan ZRAM

Pemeliharaan ZRAM akan berfungsi secara langsung, dan Anda dapat menyesuaikannya lebih lanjut menggunakan properti sistem di bagian ini.

Penjadwalan pemeliharaan ZRAM

Properti ini mengontrol cara dan waktu tugas pemeliharaan ZRAM dijadwalkan oleh system_server.

Properti Gunakan Default
mm.zram.maintenance.first_delay_seconds Penundaan sebelum pemeliharaan ZRAM pertama dimulai. 3600 (1 jam)
mm.zram.maintenance.periodic_delay_seconds Penundaan antara penjadwalan pemeliharaan ZRAM berikutnya. 3600 (1 jam)
mm.zram.maintenance.require_device_idle Apakah hanya memulai pemeliharaan ZRAM saat perangkat tidak ada aktivitas. true
mm.zram.maintenance.require_battery_not_low Apakah akan mewajibkan baterai tidak lemah sebelum memulai pemeliharaan ZRAM. true

Kebijakan penulisan balik ZRAM

Parameter berikut mengontrol kapan dan jenis memori apa yang ditulis ke perangkat pendukung:

Properti Gunakan Default
mmd.zram.writeback.backoff_seconds Waktu penundaan sejak operasi tulis balik terakhir. 600 (10 menit)
mmd.zram.writeback.min_idle_seconds Digabungkan dengan mmd.zram.writeback.max_idle_seconds untuk menghitung usia tidak ada aktivitas agar halaman memenuhi syarat untuk penulisan ulang berdasarkan fraksi penggunaan memori. Usia tidak ada aktivitas yang dihitung diinterpolasi secara eksponensial di antara kedua parameter untuk meminimalkan pekerjaan saat tidak ada tekanan memori. 72000 (20 jam)
mmd.zram.writeback.max_idle_seconds Jumlah detik maksimum yang digunakan untuk menghitung usia halaman tidak aktif secara dinamis berdasarkan penggunaan memori. 90000 (25 jam)
mmd.zram.writeback.huge.enabled Apakah akan mengaktifkan penulisan ulang halaman HUGE atau tidak. false
mmd.zram.writeback.idle.enabled Apakah akan mengaktifkan penulisan ulang halaman IDLE atau tidak. true
mmd.zram.writeback.huge_idle.enabled Apakah akan mengaktifkan penulisan ulang halaman HUGE_IDLE atau tidak. true
mmd.zram.writeback.min_bytes Jumlah minimum byte yang akan ditulis kembali dalam satu putaran penulisan kembali saat tidak ada aktivitas. 5242880 (5 MiB)
mmd.zram.writeback.max_bytes Jumlah maksimum byte yang akan ditulis kembali dalam satu putaran penulisan kembali saat tidak ada aktivitas. 314572800 (300 MiB)
mmd.zram.writeback.max_bytes_per_day Byte maksimum yang akan ditulis kembali dalam periode 24 jam. 25769803776 (24 GiB)
mmd.zram.writeback.limit.enabled Apakah akan mengaktifkan penghitungan batas anggaran penulisan balik harian. true

Kebijakan kompresi ulang ZRAM

Parameter berikut mengontrol kapan dan jenis memori apa yang dikompresi ulang:

Properti Gunakan Default
mmd.zram.recompression.backoff_seconds Waktu tunggu sejak kompresi ulang terakhir. 1800 (30 menit)
mmd.zram.recompression.min_idle_seconds Dikombinasikan dengan mmd.zram.recompression.max_idle_seconds untuk menghitung usia tidak ada aktivitas untuk halaman agar memenuhi syarat untuk dikompresi ulang berdasarkan fraksi pemanfaatan memori. Usia tidak ada aktivitas yang dihitung diinterpolasi secara eksponensial antara dua parameter untuk meminimalkan pekerjaan saat tidak dalam tekanan memori. 7200 (2 jam)
mmd.zram.recompression.max_idle_seconds Jumlah detik maksimum yang digunakan untuk menghitung usia halaman tidak ada aktivitas secara dinamis. 14400 (4 jam)
mmd.zram.recompression.threshold_bytes Ukuran minimum dalam byte halaman ZRAM yang dipertimbangkan untuk dikompresi ulang. 1024 (1 KiB)
mmd.zram.recompression.huge.enabled Apakah akan mengaktifkan HUGE kompresi ulang halaman. true
mmd.zram.recompression.idle.enabled Apakah akan mengaktifkan IDLE kompresi ulang halaman. true
mmd.zram.recompression.huge_idle.enabled Apakah akan mengaktifkan HUGE_IDLE kompresi ulang halaman. true

Pelacakan halaman tidak aktif ZRAM

mmd Pemeliharaan ZRAM menandai halaman ZRAM sebagai tidak aktif berdasarkan durasi sejak halaman tersebut terakhir kali diakses. Fitur ini memerlukan pengaktifan konfigurasi kernel CONFIG_ZRAM_TRACK_ENTRY_ACTIME atau CONFIG_ZRAM_MEMORY_TRACKING. CONFIG_ZRAM_TRACK_ENTRY_ACTIME diaktifkan secara default di kernel GKI 6.18 dan yang lebih tinggi. Pada kernel sebelumnya, fitur ini memiliki overhead memori dan tidak diaktifkan secara default.

Jika konfigurasi kernel tidak diaktifkan, pemeliharaan ZRAM akan kembali ke logika pengganti software untuk melacak halaman ZRAM yang tidak digunakan:mmd

  1. Tandai semua halaman ZRAM sebagai tidak aktif saat mmd dimulai.

  2. Lewati pemeliharaan ZRAM berikutnya hingga periode penundaan yang diperlukan telah berlalu.

  3. Penulisan ulang ZRAM atau kompresi ulang halaman yang tidak aktif. Jika masih ada halaman tidak aktif karena batas tulis balik, mmd akan terus menulis balik halaman pada pemeliharaan berikutnya tanpa menandai halaman baru sebagai tidak aktif (melewati langkah 4).

  4. Jika semua halaman tidak aktif ditulis kembali, tandai semua halaman ZRAM sebagai tidak aktif lagi dan kembali ke langkah 2. Jika penulisan ulang ZRAM dinonaktifkan, mmd akan menandai semua halaman ZRAM sebagai tidak aktif saat rekompresi ZRAM terjadi setelah durasi tidak aktif rekompresi.

Panduan pemecahan masalah dan validasi

Gunakan langkah-langkah validasi dan prosedur pemecahan masalah berikut untuk memverifikasi dan mendiagnosis operasi mmd dan ZRAM.

Memvalidasi penyiapan ZRAM

Untuk memverifikasi bahwa mmd berhasil mengonfigurasi ZRAM selama booting:

  1. Periksa algoritma kompresi aktif dan ukuran disk:

    cat /sys/block/zram0/comp_algorithm
    cat /sys/block/zram0/disksize
    
  2. Verifikasi mmdproperti sistem dan status layanan yang sedang berjalan:

    getprop | grep mmd.zram
    dumpsys -l | grep mmd
    

Memvalidasi pemeliharaan dan penulisan ulang ZRAM

Verifikasi bahwa tugas pemeliharaan penulisan ulang dan kompresi ulang ZRAM berfungsi:

  1. Periksa status perangkat blok pendukung:

    cat /sys/block/zram0/bd_stat
    
  2. Periksa efisiensi kompresi ulang dengan memantau /sys/block/zram0/mm_stat. Perubahan ukuran data terkompresi akan muncul setelah siklus pemeliharaan.

Memvalidasi penulisan balik per proses

Berikut ini dapat digunakan untuk memvalidasi bahwa penulisan balik per proses berfungsi:

  • Periksa adb logcat -s mmd untuk mengetahui log penulisan balik yang berhasil atau diagnostik kegagalan.

Masalah umum dan diagnostik

Berikut adalah situasi error umum yang mungkin dialami pengguna:

  • WritebackDailyLimitExceeded: Error ini menunjukkan bahwa kuota mmd.zram.writeback.max_bytes_per_day telah tercapai. Jika hal ini terjadi, mmd akan menjeda penulisan balik saat tidak ada aktivitas hingga periode 24 jam berlanjut.
  • Process prefetch or writeback failed: Error ini dapat diamati di logcat saat ioctl gagal. Penyebab umumnya meliputi:
    • EBADF atau ESRCH: Proses target berakhir sebelum mmd dapat mengirim pidfd ke kernel.
    • ENOSPC: Partisi penyimpanan pendukung penuh, atau antrean perangkat loop habis.
  • ZRAM tidak disiapkan: Jika mmd gagal mengonfigurasi ZRAM saat booting, hal ini mungkin disebabkan oleh skrip init vendor atau swapon_all lama yang mengunci /dev/block/zram0 sebelum mmd dapat dieksekusi.