Ringkasan pengelolaan memori

Android Runtime (ART) dan mesin virtual Dalvik menggunakan paging dan memory mapping (mmapping/pemetaan memori) untuk mengelola memori. Ini berarti setiap memori yang dimodifikasi oleh aplikasi, baik dengan mengalokasikan objek baru atau 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 itu dengan 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 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 ambang 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, dan 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 area 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 logis heap, yang dapat meningkat sesuai kebutuhan, tetapi hanya sebatas yang ditetapkan sistem untuk setiap aplikasi.

Ukuran logis heap 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 informasi lebih lanjut 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 yang 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 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 antar-aplikasi, 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 yang paling lama tidak digunakan (LRU). 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 memori yang saat ini tidak diperlukan, aplikasi Anda dapat memengaruhi performa sistem secara keseluruhan, bahkan saat pengguna tidak sedang menggunakannya. Saat memorinya menipis, sistem akan mengakhiri proses dalam cache LRU, dimulai dari yang paling lama tidak digunakan. Sistem juga memperhitungkan proses yang menggunakan memori terbanyak, dan dapat menghentikannya demi mengosongkan RAM.

Catatan: Saat mulai mengakhiri proses di cache LRU, sistem akan bekerja dari bawah ke atas. Sistem juga mempertimbangkan proses mana yang mengonsumsi lebih banyak memori dan, dengan demikian, memberikan lebih banyak memori yang diperoleh kepada sistem jika proses sudah diakhiri. Semakin sedikit memori yang Anda pakai selagi berada di daftar LRU secara keseluruhan, semakin baik peluang Anda untuk tetap berada dalam daftar dan untuk melanjutkan dengan cepat.

Untuk 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.