Android 17 dan yang lebih tinggi menyertakan Pembatas Memori, layanan sistem yang memantau dan membatasi penggunaan memori proses aplikasi menggunakan cgroup v2 Linux. Pembatas Memori mencegah setiap aplikasi mengonsumsi memori sistem yang tidak proporsional, sehingga mengurangi tekanan memori secara keseluruhan dan mencegah penghentian paksa yang agresif akibat kehabisan memori pada proses latar depan dan proses yang di-cache yang penting.
Mekanisme
Pembatas Memori terintegrasi dengan Activity Manager Service (AMS) untuk melacak peristiwa siklus proses proses dan perubahan status. Pembatas Memori menerapkan batas memori menggunakan hierarki cgroup v2 kernel Linux.
Untuk mendukung Pembatas Memori, kernel perangkat harus mengaktifkan cgroup v2 dan pengontrol memory. Layanan ini secara khusus mengandalkan atribut berikut:
memory.high- Batas yang dapat dilewati. Jika batas ini terlampaui, proses akan dibatasi dan kernel akan mencoba mengklaim kembali halaman secara proaktif dari proses tersebut.
memory.swap.max- Membatasi jumlah maksimum ruang swap (seperti ZRAM) yang dapat digunakan proses.
Dampak pada aplikasi
Aplikasi yang beroperasi dalam batas memorinya tidak akan terpengaruh oleh Pembatas Memori.
Saat aplikasi melampaui batas memory.high, kernel akan mengeluarkan memori yang didukung file
bersih aplikasi dan menukar memori anonim yang tidak aktif untuk menjaga aplikasi
tetap dalam batas. Sebagai akibat dari aktivitas pengosongan dan pertukaran halaman ini, aplikasi
mungkin mengalami throttling eksekusi sementara, tetapi terus berjalan.
Dalam situasi ekstrem—seperti kebocoran memori yang tidak terkontrol saat aplikasi terus mengalokasikan memori anonim setelah ruang swap habis—aplikasi gagal mengalokasikan memori dan dihentikan.
Pemantauan proses
Pembatas Memori memantau proses aplikasi (UID >= 10000) secara default. Proses sistem inti dikecualikan untuk menjaga stabilitas sistem yang penting.
Pembatas Memori menetapkan batas memori berdasarkan status visibilitas proses:
Proses yang terlihat: Proses yang menghosting UI yang terlihat oleh pengguna (seperti aktivitas yang saat ini difokuskan atau interaksi aktif). Karena menampilkan UI memerlukan set kerja yang lebih besar untuk pipeline rendering dan grafis, proses yang terlihat menerima batas memori yang lebih besar.
Proses tidak terlihat: Proses yang melakukan pekerjaan di latar belakang tanpa menampilkan UI (seperti layanan latar belakang atau penerima siaran). Karena tidak merender komponen UI, widget ini beroperasi di bawah batas yang lebih ketat.
Tabel berikut memetakan status proses tertentu ke klasifikasi batas memori:
| Status proses | Batas memori |
|---|---|
PERSISTENT | Tidak dibatasi |
PERSISTENT_UI | Tidak dibatasi |
TOP | Terlihat |
BOUND_TOP | Terlihat |
FOREGROUND_SERVICE | Tidak terlihat |
BOUND_FOREGROUND_SERVICE | Tidak terlihat |
IMPORTANT_FOREGROUND | Terlihat |
IMPORTANT_BACKGROUND | Tidak terlihat |
TRANSIENT_BACKGROUND | Tidak terlihat |
BACKUP | Tidak terlihat |
SERVICE | Tidak terlihat |
RECEIVER | Tidak terlihat |
TOP_SLEEPING | Terlihat |
HEAVY_WEIGHT | Tidak terlihat |
HOME | Tidak terlihat |
LAST_ACTIVITY | Tidak terlihat |
CACHED_ACTIVITY | Di-cache |
CACHED_ACTIVITY_CLIENT | Di-cache |
CACHED_RECENT | Di-cache |
CACHED_EMPTY | Di-cache |
Dalam status di-cache, proses dibekukan, lalu diklaim kembali secara maksimal.
Jika suatu proses melebihi batas memory.high yang ditetapkan, Pembatas Memori
akan mendeteksi peristiwa tersebut dan dapat memicu tindakan diagnostik, seperti mengambil
profil memori atau mencatat anomali ke statsd.
Konfigurasi
Di Android 17 dan yang lebih tinggi, Pembatas Memori dikonfigurasi menggunakan file konfigurasi platform standar di partisi sistem di /system/etc/memory-limiter-config.xml.
Format XML
File konfigurasi mengikuti skema yang ditentukan dalam
memory-limiter-config.xsd. File ini menentukan beberapa set batas yang diurutkan berdasarkan
memori yang tersedia; layanan akan memilih set batas pencocokan tertinggi berdasarkan
RAM yang tersedia di perangkat. Semua nilai memori ditentukan dalam mebibyte (MiB).
<MemoryLimiterConfig>
<version>1</version>
<configList>
<!-- RAM boundaries account for MemTotal excluding carve-outs. -->
<limitSet>
<!-- Limits for 16GB RAM device [14336, 18432): 10G/5G/5G/5G -->
<minimumRequiredMemTotal>14336</minimumRequiredMemTotal>
<maximumAllowedMemTotal>18432</maximumAllowedMemTotal>
<memVisible>10240</memVisible>
<memNotVisible>5120</memNotVisible>
<swapVisible>5120</swapVisible>
<swapNotVisible>5120</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 12GB RAM device [9216, 14336): 8G/4G/4G/4G -->
<minimumRequiredMemTotal>9216</minimumRequiredMemTotal>
<maximumAllowedMemTotal>14336</maximumAllowedMemTotal>
<memVisible>8192</memVisible>
<memNotVisible>4096</memNotVisible>
<swapVisible>4096</swapVisible>
<swapNotVisible>4096</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 8GB RAM device [6800, 9216): 5G/3G/3G/3G -->
<minimumRequiredMemTotal>6800</minimumRequiredMemTotal>
<maximumAllowedMemTotal>9216</maximumAllowedMemTotal>
<memVisible>5120</memVisible>
<memNotVisible>3072</memNotVisible>
<swapVisible>3072</swapVisible>
<swapNotVisible>3072</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 6GB RAM device [4800, 6800): 4G/2G/2G/2G -->
<minimumRequiredMemTotal>4800</minimumRequiredMemTotal>
<maximumAllowedMemTotal>6800</maximumAllowedMemTotal>
<memVisible>4096</memVisible>
<memNotVisible>2048</memNotVisible>
<swapVisible>2048</swapVisible>
<swapNotVisible>2048</swapNotVisible>
</limitSet>
<limitSet>
<!-- Limits for 4GB RAM device [3200, 4800): 2G/1G/1G/1G -->
<minimumRequiredMemTotal>3200</minimumRequiredMemTotal>
<maximumAllowedMemTotal>4800</maximumAllowedMemTotal>
<memVisible>2048</memVisible>
<memNotVisible>1024</memNotVisible>
<swapVisible>1024</swapVisible>
<swapNotVisible>1024</swapNotVisible>
</limitSet>
</configList>
</MemoryLimiterConfig>
version- Bilangan bulat positif yang mengidentifikasi versi konfigurasi. Nilai ini harus berupa
1. minimumRequiredMemTotalMemTotalsistem minimum (dalam MiB, batas bawah inklusif) yang diperlukan agar set batas ini berlaku. Layanan ini mengevaluasi hal ini terhadap total memori yang tersedia yang dilaporkan oleh kernel di/proc/meminfo.Memahami alokasi dan batas memori: Nilai
MemTotalkernel mencerminkan DRAM fisik yang dapat diakses oleh sistem operasi setelah alokasi memori hardware dan firmware dikurangi. Carve-out mencadangkan RAM untuk komponen hardware khusus seperti GPU, modem baseband, ISP kamera, lingkungan eksekusi yang aman, dan hypervisor, yang biasanya menggunakan antara 500 MiB dan lebih dari 2 GiB memori fisik.Karena
MemTotallebih rendah daripada DRAM fisik yang diiklankan perangkat, nilai minimumminimumRequiredMemTotalmenyertakan margin untuk carve-out ini. Misalnya, konfigurasi yang menargetkan perangkat 16 GB menentukan batas bawah14336(14 GiB), bukan16384(16 GiB), dan tingkat untuk perangkat 12 GB menentukan batas bawah9216(9 GiB). Hal ini memastikan bahwa setiap perangkat cocok dengan tingkat yang diinginkan, terlepas dari variasi pembagian di tingkat board.maximumAllowedMemTotalMemTotalsistem maksimum (dalam MiB, batas atas eksklusif) agar set batas ini berlaku. JikaMemTotallebih besar dari atau sama dengan batas ini, batas yang ditetapkan tidak berlaku. Untuk perangkat dengan 18.432 MiB atau lebih atau untuk perangkat dengan kurang dari 3.200 MiB, Pembatas Memori tidak menerapkan batasan, sehingga proses tidak dibatasi.memVisibleBatas memori ringan (
memory.high) dalam MiB yang diterapkan ke proses yang terlihat.memNotVisibleBatas memori sementara (
memory.high) dalam MiB yang diterapkan ke proses yang tidak terlihat.swapVisibleBatas ruang swap (
memory.swap.max) dalam MiB yang diterapkan ke proses yang terlihat.swapNotVisibleBatas ruang swap (
memory.swap.max) dalam MiB yang diterapkan ke proses yang tidak terlihat.
Batas platform standar
Di Android 17 dan yang lebih tinggi, platform menentukan batas memori dan swap standar
di /system/etc/memory-limiter-config.xml di seluruh tingkat RAM fisik umum
menggunakan interval rentang [floor, ceiling):
| RAM fisik target |
Rentang MemTotal [floor, ceiling) (minimumRequiredMemTotal, maximumAllowedMemTotal) |
Batas memori yang terlihat (memVisible) |
Batas memori tidak terlihat (memNotVisible) |
Batas swap yang terlihat (swapVisible) |
Batas penukaran tidak terlihat (swapNotVisible) |
|---|---|---|---|---|---|
| 16 GB | [14336, 18432) MiB |
10.240 MiB (10 GiB) | 5.120 MiB (5 GiB) | 5.120 MiB (5 GiB) | 5.120 MiB (5 GiB) |
| 12 GB | [9216, 14336) MiB |
8.192 MiB (8 GiB) | 4.096 MiB (4 GiB) | 4.096 MiB (4 GiB) | 4.096 MiB (4 GiB) |
| 8 GB | [6800, 9216) MiB |
5.120 MiB (5 GiB) | 3.072 MiB (3 GiB) | 3.072 MiB (3 GiB) | 3.072 MiB (3 GiB) |
| 6 GB | [4800, 6800) MiB |
4.096 MiB (4 GiB) | 2.048 MiB (2 GiB) | 2.048 MiB (2 GiB) | 2.048 MiB (2 GiB) |
| 4 GB | [3200, 4800) MiB |
2.048 MiB (2 GiB) | 1.024 MiB (1 GiB) | 1.024 MiB (1 GiB) | 1.024 MiB (1 GiB) |
Prinsip batas memori
Konfigurasi Pembatas Memori dirancang berdasarkan prinsip platform berikut:
Konsistensi ekosistem dan kompatibilitas aplikasi: Batas memori yang konsisten di seluruh perangkat memastikan performa aplikasi yang dapat diprediksi di seluruh ekosistem Android. Aplikasi dikembangkan dan diuji berdasarkan ekspektasi memori standar; mempertahankan batas platform yang seragam akan menghindari throttling yang tidak terduga atau penghentian dini.
Alokasi resource proporsional: Batas platform dikalibrasi sesuai dengan kapasitas RAM fisik:
- Proses yang terlihat: Mengalokasikan sekitar 1/2 hingga 2/3 dari total RAM fisik untuk mendukung workload UI, komposisi, dan rendering yang aktif.
- Proses yang tidak terlihat: Mengalokasikan sekitar 1/4 hingga 1/3 dari total RAM fisik untuk tugas latar belakang.
Penerapan universal: Batas berlaku secara seragam untuk semua proses aplikasi di perangkat (UID >= 10000), termasuk aplikasi sistem dan OEM bawaan. Pembatas Memori tidak mendukung daftar yang diizinkan untuk mengecualikan aplikasi tertentu, sehingga memastikan tata kelola memori yang adil di semua aplikasi. Untuk mengonfigurasi batas bawah perlindungan
memory.minyang dapat menyesuaikan sendiri pada daemon interaktif penting dan batas atasmemory.highyang lebih ketat dan dikalibrasi workload pada setiap aplikasi dan layanan sistem, lihat Anggaran memori sistem.Tidak adanya API kueri runtime: Di Android 17 dan yang lebih tinggi, aplikasi tidak dapat membuat kueri batas memori yang ditetapkan secara terprogram saat runtime. Batas platform standar ditentukan dengan margin yang besar sehingga aplikasi yang berperilaku baik dapat beroperasi tanpa batasan selama penggunaan normal.
Dinamika reclaim dan swap kernel: Saat proses aplikasi mendekati batas
memory.high, kernel Linux mengarahkan reclaim memori secara khusus ke cgroup proses tersebut. Hal ini termasuk menghapus halaman yang didukung file yang tidak aktif dan menukar halaman anonim yang tidak aktif ke ZRAM, sehingga menjaga kelancaran sistem tanpa membebani memori global.
Perintah shell
Perintah am memory-limiter memungkinkan developer dan integrator sistem berinteraksi
dengan layanan saat runtime untuk pengembangan, pengujian, dan proses debug:
am memory-limiter <SUB-COMMAND>status
Subperintah status melaporkan status operasional dan metrik aktif
Pembatas Memori:
adb shell am memory-limiter statusBerikut adalah contoh output:
Memory limiter
enabled monitoring=true ignored=none
visibleMem=1948MB visibleSwap=974MB
notVisibleMem=974MB notVisibleSwap=487MB
started=36 watched=36 watch-failed=0
events=0 processes=36 process-hwm=36
Kolom utama dalam output mencakup:
monitoring- Menunjukkan apakah Pembatas Memori secara aktif memantau proses.
visibleMemdannotVisibleMem- Batas memori absolut yang dihitung (
memory.high) yang saat ini diterapkan untuk setiap status visibilitas. visibleSwapdannotVisibleSwap- Batas swap absolut yang dihitung (
memory.swap.max) saat ini diterapkan untuk setiap status visibilitas. events- Berapa kali proses melampaui batas yang ditetapkan.
processes- Jumlah proses yang dipantau saat ini.
ignore
Subperintah ignore mengecualikan UID tertentu atau semua proses
dari pembatasan memori untuk sementara. Hal ini berguna untuk tolok ukur performa, pengujian
stres, atau mendiagnosis perilaku memori:
# Ignore a specific UID adb shell am memory-limiter ignore 10087# Ignore all processes (temporarily disables limiting) adb shell am memory-limiter ignore all# Resume normal limiting operation adb shell am memory-limiter ignore none
manual
Subperintah manual mengganti batas yang dihitung untuk proses tertentu
berdasarkan ID proses (PID) dengan nilai absolut kustom dalam byte. Nilai harus berupa
bilangan bulat, tetapi dapat menyertakan akhiran MB untuk menunjukkan MiB atau akhiran GB untuk
menunjukkan GiB:
# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1073741824# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1024MB# Set a 1GiB limit for PID 1234 adb shell am memory-limiter manual 1234 1GB# Remove the manual override for PID 1234 adb shell am memory-limiter manual 1234 none
Penggantian manual hanya berlaku selama masa aktif instance proses tertentu tersebut. Jika proses dimulai ulang, proses tersebut akan kembali ke batas standar berdasarkan statusnya.
Penggantian manual tidak boleh melebihi batas sistem fisik.