Untuk mengoptimalkan jejak memori game Anda secara efektif, Anda harus terlebih dahulu memahami cara platform Android mengukur memori dan cara menggunakan telemetri sistem, API diagnostik, dan alat pembuatan profil. Panduan ini menjelaskan cara memantau, merekam, dan menganalisis alokasi memori game Anda berdasarkan pedoman platform baru.
Memahami metrik RSS dan penukaran
Untuk menganalisis dan men-debug perilaku memori game secara efektif, Anda harus memahami metrik teknis persis yang digunakan platform Android untuk penegakan memori. Untuk mengetahui informasi latar belakang mendetail tentang cara parameter telemetri ini diproses dan dipantau di lapangan, lihat dokumentasi Android Vitals - Penggunaan memori (RSS anonim + swap).
1. RSS Anonim (RssAnon)
Resident Set Size (RSS) mengukur bagian memori yang ditempati oleh proses yang disimpan dalam RAM fisik perangkat. RSS dibagi menjadi memori yang didukung file dan memori anonim. Metrik penegakan kebijakan Android berfokus sepenuhnya pada RSS Anonim:
- Yang disertakan: Halaman memori yang dialokasikan langsung oleh proses game Anda yang tidak ditautkan ke file fisik di penyimpanan. Halaman ini mencakup heap Java atau Kotlin, stack eksekusi thread, dan yang paling penting, alokasi memori native (seperti alokator mesin C++ kustom, atau blok memori yang diminta menggunakan malloc atau new native dan dikotori oleh logika game). Pelajari lebih lanjut metrik ini di kamus Process Memory (RSS).
- Mengapa ini penting: Mesin game menggunakan kumpulan memori native yang besar untuk menangani fisika, rendering, dan logika. Karena kumpulan ini tidak didukung oleh file, kumpulan ini sepenuhnya berada di RSS Anonim dan membentuk sebagian besar jejak fisik game Anda.
2. Pertukaran tidak terkompresi (VmSwap)
Android tidak mendukung ruang swap berbasis disk tradisional karena batasan keausan dan latensi penyimpanan flash. Sebagai gantinya, perangkat ini menggunakan zRAM (Swap yang Tidak Dikompresi):
- Yang disertakan: Saat tekanan RAM fisik meningkat, daemon pengelolaan memori kernel akan mengompresi halaman anonim yang tidak aktif dan memindahkannya ke bagian RAM fisik yang tidak dikompresi dan khusus (zRAM).
- Penghitungan metrik: Sistem melacak ini berdasarkan ukuran yang tidak dikompresi (VmSwap) untuk mengevaluasi permintaan memori fisik sebenarnya dari game. Jika game Anda mengalokasikan memori dan sistem menukarnya ke zRAM, memori tersebut tetap dihitung dalam Total Jejak Memori game Anda.
3. Status proses
Penggunaan memori dipecah berdasarkan status proses di Android Vitals. Untuk developer game, SDK atau game pihak ketiga juga dapat memicu layanan yang dirasakan pengguna atau layanan latar belakang secara tidak terduga.
- Yang disertakan: Latar Depan, Layanan yang Dapat Dirasakan, Latar Belakang, dan Di-cache.
- Mengapa hal ini penting: Status proses yang berbeda memiliki dampak yang berbeda pada pengelolaan memori OS Android. Anda mungkin tidak tahu bahwa game Anda berjalan dengan status proses sensitif jika ada SDK pihak ketiga yang memicu tugas latar belakang secara tidak sengaja. Pantau apakah game Anda berjalan di latar belakang
menggunakan
RunningAppProcessInfo.
Application programming interface (API)
Android menyediakan API sistem yang memungkinkan game Anda merespons secara dinamis terhadap tekanan memori dan merekam diagnostik memori mendetail saat runtime.
Merespons peristiwa pemangkasan memori
Sistem menggunakan onTrimMemory untuk memberi tahu aplikasi Anda tentang peristiwa siklus proses yang
memberikan peluang yang baik bagi aplikasi Anda untuk secara sukarela mengurangi penggunaan memorinya
dan menghindari dihentikan oleh penghentian karena memori rendah (LMK) untuk melepaskan memori agar dapat digunakan oleh
aplikasi lain.
Jika sistem menghentikan aplikasi Anda di latar belakang, pengguna akan mengalami cold start yang lambat saat melanjutkan. Mengurangi penggunaan memori di latar belakang membantu mencegah penghentian di latar belakang ini.
Saat merespons peristiwa pemangkasan, lepaskan alokasi memori besar yang dapat direkonstruksi dan tidak diperlukan segera:
Contoh: Pangkas atau hapus bitmap yang di-cache (didekode dari penyimpanan lokal) sebagai respons terhadap
TRIM_MEMORY_UI_HIDDEN.
Kotlin
class MainActivity : AppCompatActivity(), ComponentCallbacks2 {
override fun onTrimMemory(level: Int) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
Java
public class MainActivity extends AppCompatActivity implements ComponentCallbacks2 {
public void onTrimMemory(int level) {
switch (level) {
if (level >= ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN) {
// Release memory related to UI elements, such as bitmap caches.
}
if (level >= ComponentCallbacks2.TRIM_MEMORY_BACKGROUND) {
// Release memory related to background processing, such as by
// closing a database connection.
}
}
}
}
ProfilingManager
Diperkenalkan di Android 15 (level API 35), API ProfilingManager memungkinkan aplikasi mengambil snapshot yang ditentukan secara terprogram (seperti profil heap, rekaman aktivitas sistem, dan dump heap Java) secara langsung saat runtime.
Developer dapat memicu pengambilan gambar secara manual pada adegan tertentu, atau mendaftarkan pemicu otomatis seperti TRIGGER_TYPE_ANOMALY untuk otomatis memicu pengambilan gambar saat proses game melanggar batas Memory Limiter. Namun, developer game harus memperhitungkan batasan penting dalam mesin game modern:
Catatan: Mesin game modern (seperti Unity atau Unreal) mengelola performa eksekusi dengan melakukan pra-alokasi blok memori virtual besar dari kernel menggunakan mmap dengan tanda MAP_ANONYMOUS. Mesin kemudian menggunakan sub-pengalokasi kustom (misalnya, pengelola memori native Unity atau BinnedAllocators Unreal) untuk membagi dan mengalokasikan blok memori secara internal.
ApplicationExitInfo
Jika game Anda dihentikan di latar belakang atau dihentikan karena melanggar batas memori proses individual, mekanisme dump error Java atau native standar (seperti Firebase Crashlytics) tidak akan mendaftarkan peristiwa tersebut. Untuk mengirimkan kueri dan mencatat penghentian ini secara terprogram, developer harus memanfaatkan API ApplicationExitInfo saat game dimulai.
- Penerapan: Saat dimulai, panggil
ActivityManager.getHistoricalProcessExitReasons()untuk mengambil alasan keluar dari sesi terbaru. - Alasan keluar dari memori utama:
REASON_LOW_MEMORY: Menunjukkan bahwa proses dihentikan oleh Low Memory Killer (LMK) sistem. Penghentian ini terjadi saat tekanan memori di seluruh perangkat tinggi dan OS harus mengklaim kembali RAM. Alasan keluar ini menunjukkan bahwa footprint latar belakang game Anda terlalu besar untuk berdampingan dengan aplikasi lain.REASON_MEMORY_LIMITER(Android 17 (level API 37) dan yang lebih tinggi): Menunjukkan bahwa proses dihentikan secara khusus karena melampaui batas memori cgroup (RssAnon + VmSwap) yang ditetapkan oleh Pembatas Memori platform. Penghentian ini dapat terjadi meskipun masih ada memori fisik yang cukup di perangkat, yang menandakan pelanggaran langsung terhadap batas proses individual.
Menggunakan fitur yang tersedia
Gunakan alat platform berikut selama pengembangan dan QA untuk mengukur penggunaan memori game Anda secara akurat.
meminfo
Alat ini mengumpulkan statistik memori untuk menunjukkan berapa banyak memori PSS yang dialokasikan dan kategori penggunaannya.
Cetak statistik meminfo dengan salah satu cara berikut:
- Gunakan perintah
adb shell dumpsys meminfo package-name. - Gunakan panggilan
MemoryInfodari Debug API Android.
Statistik PrivateDirty menunjukkan jumlah RAM di dalam proses
yang tidak dapat di-paging ke disk dan tidak dibagikan dengan proses lain. Sejumlah besar ini akan tersedia untuk sistem saat proses tersebut dihentikan.
Tracepoint memori
Tracepoint memori melacak jumlah memori RSS yang digunakan game Anda. Menghitung penggunaan memori RSS jauh lebih cepat daripada menghitung penggunaan PSS. Karena penghitungannya lebih cepat, RSS menunjukkan perincian yang lebih baik pada perubahan ukuran memori untuk pengukuran penggunaan memori puncak yang lebih akurat. Oleh karena itu, sebaiknya lihat puncak yang dapat menyebabkan game kehabisan memori.
Perfetto
Perfetto adalah rangkaian alat untuk mengumpulkan informasi performa dan memori di perangkat dan menampilkannya di UI berbasis web. Alat ini mendukung rekaman aktivitas panjang secara bebas sehingga Anda dapat melihat perubahan RSS seiring waktu. Anda juga dapat
mengeluarkan kueri SQL mengenai data yang dihasilkan untuk pemrosesan offline. Aktifkan rekaman aktivitas panjang dari aplikasi Pelacakan Sistem. Pastikan kategori memory:Memory diaktifkan untuk rekaman aktivitas. Untuk instrumentasi memori kustom dalam pengembangan dan pengujian, Anda juga dapat menggunakan heapprofd API (Beta).
Memeriksa RssAnon dan menukarnya di Perfetto
Untuk memeriksa dampak memori anonim dan swap zRAM game Anda, muat file rekaman aktivitas di UI berbasis web di ui.perfetto.dev dan ikuti teknik analisis berikut, yang dirancang untuk studi kasus memori mendalam (lihat Studi Kasus Analisis Memori Perfetto untuk mengetahui detail selengkapnya):
1. Memvisualisasikan Penghitung Memori di Linimasa
- Temukan proses Anda: Di daftar navigasi, telusuri nama paket atau proses game Anda.
- Luaskan grup rekaman aktivitas: Klik baris proses Anda untuk meluaskan rekaman aktivitas thread-nya, dan temukan sub-grup bernama Memori.
- Analisis jalur:
- mem.rss.anon (RSS Anonim): Grafik garis ini menampilkan RAM fisik real-time yang digunakan oleh kumpulan memori tidak terkelola game Anda. Pantau linimasa ini selama pemuatan adegan, pop-up UI, atau transisi gameplay untuk memeriksa puncak alokasi yang tinggi.
- mem.swap (Swap Terkompresi atau VmSwap): Grafik ini memetakan ukuran blok memori yang dipindahkan ke zRAM sebelum dikompresi. Aktivitas swap yang tinggi yang bertepatan dengan gameplay menunjukkan bahwa game Anda berjalan di perangkat dengan memori terbatas dan sistem secara aktif mengompresi aset latar belakang.
2. Menjalankan Kueri SQL (Trace Processor) Untuk analisis offline yang mendetail, Anda dapat menjalankan kueri SQL langsung di dalam konsol UI Perfetto atau menggunakan library Python Trace Processor mandiri untuk menghitung puncak statistik.
Temukan Alokasi RSS Anonim Puncak:
SELECT max(value) / 1024 / 1024 AS max_rss_anon_mb FROM counter JOIN counter_track ON counter.track_id = counter_track.id WHERE counter_track.name = 'mem.rss.anon' AND counter_track.upid IN ( SELECT upid FROM process WHERE name = 'your.game.package.name' );Korelasikan RssAnon dan VmSwap pada stempel waktu tertentu:
SELECT ts, track.name AS metric_type, value / 1024 / 1024 AS size_mb FROM counter JOIN counter_track track ON counter.track_id = track.id WHERE (track.name = 'mem.rss.anon' OR track.name = 'mem.swap') AND track.upid IN ( SELECT upid FROM process WHERE name = 'your.game.package.name' ) ORDER BY ts ASC;
Untuk mengetahui detail selengkapnya tentang cara memeriksa file rekaman aktivitas menggunakan Android Studio, lihat Memeriksa rekaman aktivitas sistem: Memori Proses (RSS). Untuk mengetahui detail tentang pembuatan skrip profil memori, lihat Merekam alokasi native.
heapprofd
heapprofd adalah alat pelacakan memori yang merupakan bagian dari Perfetto. Alat ini
dapat membantu Anda menemukan kebocoran memori dengan menunjukkan lokasi alokasi memori menggunakan
malloc. heapprofd dapat dimulai menggunakan skrip Python, dan karena alat memiliki overhead yang rendah, hal ini tidak memengaruhi performa layaknya alat lain seperti Malloc Debug.
bugreport
bugreport adalah alat logging untuk mengetahui apakah game Anda mengalami error atau tidak
karena kehabisan memori. Output alat ini jauh lebih detail daripada jika menggunakan
logcat. Hal ini berguna untuk melakukan proses debug memori karena menunjukkan apakah game Anda mengalami error
karena kehabisan memori atau jika ditutup oleh LMK.
Untuk mengetahui informasi selengkapnya, lihat Merekam dan membaca laporan bug.
Alat game engine
Meskipun log tingkat platform dan telemetri sistem sangat penting untuk melacak nilai minimum dan kepatuhan OS, alat khusus mesin game membantu Anda mengatribusikan alokasi langsung kembali ke objek game, perilaku skrip, dan hierarki adegan aktif.
Unity
Di lingkungan Unity Engine, Anda dapat memperkirakan secara cermat jejak memori RSS + Swap Anonim Android saat runtime dengan keandalan tinggi (biasanya menampilkan varians kurang dari 10% dibandingkan dengan nilai tingkat OS yang sebenarnya) menggunakan alat dan class profiling native Unity.
Untuk tutorial langkah demi langkah yang lengkap, termasuk aturan konfigurasi dan skrip runtime, lihat Cara memeriksa memori dengan alat Unity.
- Unity profiler API: Anda dapat memperkirakan footprint memori tidak terkelola game Anda secara terprogram saat runtime dengan membuat kueri metrik mesin inti:
- Menggunakan class Profiler: Lacak total alokasi memori dengan menjumlahkan nilai
Profiler.GetTotalReservedMemoryLong()danProfiler.GetMonoHeapSizeLong(). - Menggunakan class
ProfilerRecorder: Pantau kategori memori secara dinamis. Untuk membuat perkiraan dasar yang andal, ambil Total Reserved Memory (pada build Rilis) atau kurangi Gfx Reserved Memory dari Total Reserved Memory (pada build Pengembangan) untuk menghapus komponen memori grafis yang didukung file.
- Menggunakan class Profiler: Lacak total alokasi memori dengan menjumlahkan nilai
- Unity Memory Profiler: Untuk mengidentifikasi dan men-debug kebocoran memori secara offline,
ambil snapshot memori dan periksa diagram Resident Memory on Device
yang ada di bagian All of Memory. Untuk menghitung perkiraan
jejak, jumlahkan total kategori berikut: Tidak Dilacak, Android
Runtime, Native, dan Terkelola.
- Batasan zRAM: Dalam kondisi memori yang terbatas, kernel Android dapat mengompresi halaman memori yang tidak aktif ke ruang swap (zRAM). Karena Unity Memory Profiler tidak dapat mendeteksi parameter swap tingkat OS, Anda mungkin melihat sedikit perbedaan jejak selama adegan memori berat. Lakukan referensi silang perkiraan Anda dengan Perfetto untuk mengonfirmasi nilai yang tepat.