Ringkasan pengelolaan memori

Android Runtime (ART) dan mesin virtual Dalvik menggunakan paging dan memory mapping (mmapping/pemetaan memori) untuk mengelola memori. Hal ini berarti setiap memori yang dimodifikasi oleh aplikasi—baik dengan mengalokasikan objek baru maupun mengakses halaman yang di-mmap—tetap berada di dalam RAM dan tidak dapat di-page out. Satu-satunya cara untuk membebaskan memori dari aplikasi adalah dengan melepaskan referensi objek yang digunakan aplikasi, sehingga memori tersedia bagi pembersih sampah memori. Namun, cara tersebut memiliki satu pengecualian: setiap file yang di-mmap masuk tanpa modifikasi, misalnya kode, dapat di-page out dari RAM jika sistem ingin menggunakan memori tersebut di tempat lain.

Artikel ini menjelaskan cara Android mengelola proses aplikasi dan alokasi memori. Untuk mengetahui informasi selengkapnya tentang cara mengelola memori secara lebih efisien di aplikasi Anda, lihat Mengelola Memori Aplikasi.

Pembersihan sampah memori

Lingkungan memori terkelola, seperti ART atau mesin virtual Dalvik, melacak setiap alokasi memori. Setelah menentukan bahwa memori tidak lagi digunakan oleh program, lingkungan memori terkelola akan mengembalikan memori tersebut ke heap, tanpa intervensi apa pun dari programmer. Mekanisme untuk mengklaim kembali memori yang tidak terpakai dalam lingkungan memori terkelola ini disebut pembersihan sampah memori. Pembersihan sampah memori memiliki dua tujuan: menemukan objek data dalam program yang tidak dapat diakses di waktu mendatang, dan mengklaim kembali resource yang digunakan oleh objek tersebut.

Heap memori Android bersifat generasional, yang berarti ada berbagai bucket alokasi yang dilacak, berdasarkan ekspektasi umur dan ukuran objek yang dialokasikan. Misalnya, objek yang baru dialokasikan termasuk dalam Generasi muda. Jika sebuah objek tetap aktif cukup lama, objek tersebut dapat dipromosikan ke generasi yang lebih tua, yang diikuti oleh generasi permanen.

Setiap generasi heap memiliki batas atas khusus terkait banyaknya memori yang dapat ditempati oleh objek yang ada di sana. Setiap kali generasi mulai terisi, sistem akan menjalankan peristiwa pembersihan sampah memori sebagai upaya untuk mengosongkan memori. Durasi pembersihan sampah memori bergantung pada generasi objek yang dibersihkan dan banyaknya objek aktif di setiap generasi.

Meskipun pembersihan sampah memori berlangsung sangat cepat, proses ini tetap dapat memengaruhi performa aplikasi Anda. Secara umum, Anda tidak dapat mengontrol kapan peristiwa pembersihan sampah memori terjadi dari dalam kode. Sistem memiliki sekumpulan kriteria aktif untuk menentukan kapan pembersihan sampah memori harus dijalankan. Saat kriteria ini terpenuhi, sistem akan berhenti menjalankan proses dan memulai pembersihan sampah memori. Jika pembersihan sampah memori terjadi di tengah-tengah loop pemrosesan yang intensif, seperti animasi atau selama pemutaran musik, pembersihan sampah memori dapat meningkatkan waktu proses. Peningkatan ini berpotensi mendorong eksekusi kode di aplikasi Anda melampaui batas 16 milidetik yang disarankan untuk proses rendering frame yang efisien dan lancar.

Selain itu, alur kode Anda dapat menjalankan jenis pekerjaan yang memaksa terjadinya pembersihan sampah memori lebih sering, atau menjadikannya berlangsung lebih lama daripada biasanya. Misalnya, jika Anda mengalokasikan beberapa objek di bagian terdalam for-loop selama setiap frame animasi pencampuran alfa, Anda dapat mengotori heap memori dengan banyak objek. Dalam situasi tersebut, pembersih sampah memori akan menjalankan beberapa peristiwa pembersihan sampah memori, dan hal itu dapat menurunkan performa aplikasi Anda.

Untuk informasi umum lebih lanjut tentang pembersihan sampah memori, lihat Pembersihan sampah memori.

Membagikan memori

Agar sesuai dengan semua yang dibutuhkan di RAM, Android mencoba membagikan halaman RAM ke berbagai proses. Android melakukannya dengan cara berikut:

  • Setiap proses aplikasi diambil dari proses yang sudah ada, yang disebut Zygote. Proses Zygote dimulai ketika sistem melakukan booting dan memuat kode framework dan resource yang umum (seperti tema aktivitas). Untuk memulai proses aplikasi baru, sistem akan mengambil proses Zygote, lalu memuat dan menjalankan kode aplikasi dalam proses baru. Dengan pendekatan ini, sebagian besar halaman RAM yang dialokasikan untuk kode framework dan resource dapat dibagikan ke semua proses aplikasi.
  • Sebagian besar data statis di-mmap masuk ke dalam proses. Dengan teknik ini, data dapat dibagikan ke berbagai proses, juga memungkinkan data untuk di-page out saat diperlukan. Contoh data statis meliputi: kode Dalvik (dengan menempatkannya dalam file .odex yang ditautkan sebelumnya untuk mmapping langsung), resource aplikasi (dengan mendesain tabel resource menjadi struktur yang dapat di-mmap, dan dengan menyelaraskan entri zip APK), serta elemen project tradisional seperti kode native dalam file .so.
  • Di banyak tempat, Android berbagi RAM dinamis yang sama dengan berbagai proses menggunakan region memori bersama yang dialokasikan secara eksplisit (dengan ashmem atau gralloc). Misalnya, tampilan jendela menggunakan memori bersama antara aplikasi dan compositor layar, dan buffer kursor menggunakan memori bersama antara penyedia konten dan klien.

Karena penggunaan memori bersama yang ekstensif, diperlukan kecermatan untuk menentukan banyaknya memori yang digunakan aplikasi. Teknik untuk menentukan penggunaan memori aplikasi dengan tepat dibahas dalam Menyelidiki Penggunaan RAM.

Mengalokasikan dan mengklaim kembali memori aplikasi

Heap Dalvik dibatasi ke satu rentang memori virtual untuk setiap proses aplikasi. Hal ini menentukan ukuran heap logika, yang dapat meningkat sesuai kebutuhan, tetapi hanya sebatas yang ditetapkan sistem untuk setiap aplikasi.

Ukuran heap logis tidak sama dengan jumlah memori fisik yang digunakan oleh heap. Saat memeriksa heap aplikasi, Android menghitung sebuah nilai yang disebut Proportional Set Size (PSS, Ukuran Set Proporsional), yang memperhitungkan halaman kotor dan bersih yang digunakan bersama dengan proses lain—tetapi hanya sejumlah yang proporsional dengan banyaknya aplikasi yang menggunakan bersama RAM tersebut. Total (PSS) ini adalah apa yang dianggap sistem sebagai jejak memori fisik Anda. Untuk mengetahui informasi selengkapnya tentang PSS, lihat panduan Menyelidiki Penggunaan RAM .

Heap Dalvik tidak memadatkan ukuran logis heap, yang berarti Android tidak mendefragmentasi heap untuk menutup ruang. Android hanya dapat menyusutkan ukuran logis heap jika ada ruang tidak terpakai di akhir heap. Namun, sistem masih dapat mengurangi memori fisik yang digunakan oleh heap. Setelah pembersihan sampah memori, Dalvik menjalankan heap dan menemukan halaman yang tidak terpakai, lalu mengembalikan halaman tersebut ke kernel menggunakan madvise. Jadi, pasangan alokasi dan dealokasi untuk bagian memori yang besar akan menghasilkan pemerolehan kembali semua (atau hampir semua) memori fisik yang digunakan. Namun, pemerolehan kembali memori dari alokasi kecil dapat menjadi jauh tidak efisien karena halaman yang digunakan untuk alokasi kecil masih dapat dibagikan dengan sesuatu yang belum dibebaskan.

Membatasi memori aplikasi

Agar lingkungan multitasking tetap fungsional, Android menetapkan batas pasti ukuran heap untuk setiap aplikasi. Batas ukuran heap pasti ini bervariasi antarperangkat, tergantung banyaknya RAM yang dimiliki perangkat secara keseluruhan. Jika telah mencapai kapasitas heap dan mencoba mengalokasikan lebih banyak memori, aplikasi Anda akan menerima OutOfMemoryError.

Dalam beberapa kasus, sebaiknya Anda mengkueri sistem untuk mengetahui secara pasti banyaknya ruang heap yang Anda miliki di perangkat saat ini—misalnya, untuk menentukan banyaknya data yang dapat disimpan dengan aman di dalam cache. Untuk mengetahui angkanya, panggil getMemoryClass(). Metode ini menampilkan bilangan bulat yang menunjukkan jumlah megabyte yang tersedia untuk heap aplikasi Anda.

Beralih aplikasi

Saat pengguna beralih antaraplikasi, Android akan menyimpan aplikasi yang tidak berjalan di latar depan—artinya, yang tidak terlihat oleh pengguna atau menjalankan layanan latar depan, seperti pemutaran musik— di dalam cache. Misalnya, saat pengguna meluncurkan aplikasi untuk pertama kalinya, sebuah proses akan dibuat untuk peristiwa tersebut; tetapi saat pengguna menutup aplikasi, proses tersebut tidak berhenti. Sistem menyimpannya di dalam cache. Jika nanti pengguna kembali ke aplikasi itu, sistem akan menggunakan kembali proses tersebut, sehingga peralihan aplikasi berlangsung lebih cepat.

Jika memiliki proses yang tersimpan dalam cache dan mempertahankan resource yang saat ini tidak diperlukan, aplikasi Anda—bahkan saat pengguna tidak sedang menggunakannya— dapat memengaruhi performa sistem secara keseluruhan. Jika resource seperti memori hampir penuh, sistem akan mengakhiri proses dalam cache. Sistem juga memperhitungkan proses yang menggunakan memori terbanyak, dan dapat menghentikannya untuk mengosongkan RAM.

Catatan: Makin sedikit memori yang digunakan aplikasi Anda selagi berada dalam cache, makin baik peluangnya untuk tetap berjalan dan untuk melanjutkan dengan cepat. Namun, bergantung pada persyaratan sistem yang berlangsung dengan sangat cepat, proses yang disimpan dalam cache dapat dihentikan kapan saja, tanpa memperhitungkan pemakaian resource.

Untuk mengetahui informasi selengkapnya tentang bagaimana proses disimpan di cache saat tidak berjalan di latar depan, dan bagaimana Android menentukan proses mana yang dapat diakhiri, lihat panduan Proses dan Thread.

Stress testing memori

Meskipun masalah stress memori jarang terjadi pada perangkat kelas atas, masalah tersebut masih dapat menyebabkan masalah bagi pengguna di perangkat dengan RAM rendah, seperti yang menjalankan Android (edisi Go). Penting untuk mencoba dan membuat ulang lingkungan memori yang sudah diuji stress testing ini agar Anda dapat menulis uji instrumentasi untuk memverifikasi perilaku aplikasi dan meningkatkan pengalaman bagi pengguna di perangkat dengan memori rendah.

Stressful Application Test

Stressful Application Test (stressapptest) adalah pengujian antarmuka memori yang membantu menciptakan situasi yang realistis dan memiliki beban tinggi untuk menguji berbagai keterbatasan memori dan hardware untuk aplikasi Anda. Dengan kemampuan untuk menentukan waktu dan batasan memori, hal ini memungkinkan Anda menulis instrumentasi untuk memverifikasi pengalaman nyata di situasi memori tinggi. Misalnya, gunakan rangkaian perintah berikut untuk menerapkan library statis di sistem file data Anda, membuatnya dapat dieksekusi, dan menjalankan stress testing selama 20 detik dari 990 MB:
    adb push stressapptest /data/local/tmp/
    adb shell chmod 777 /data/local/tmp/stressapptest
    adb shell /data/local/tmp/stressapptest -s 20 -M 990

  

Lihat dokumentasi stressapptest untuk mengetahui informasi selengkapnya tentang cara menginstal alat, argumen umum, dan informasi penanganan error.

Pengamatan pada stressapptest

Alat seperti stressapptest dapat digunakan untuk meminta alokasi memori yang lebih besar daripada yang tersedia secara bebas. Permintaan semacam ini dapat memicu berbagai pemberitahuan, yang harus Anda ketahui dari sisi pengembangan. Tiga pemberitahuan utama yang dapat dimunculkan karena ketersediaan memori yang rendah meliputi:
  • SIGABRT: Error ini bersifat fatal dan native untuk proses Anda karena meminta alokasi dengan ukuran lebih besar dari memori bebas, saat sistem sudah berada di bawah tekanan memori.
  • SIGQUIT: Menghasilkan dump memori inti dan menghentikan proses saat terdeteksi oleh uji instrumentasi Anda.
  • TRIM_MEMORY_EVENTS: Callback ini tersedia di Android 4.1 (API level 16) dan lebih tinggi, serta memberikan pemberitahuan memori yang mendetail untuk proses Anda.