Persyaratan memori besar di Android - apa yang harus dilakukan?

Halo pembaca yang budiman.

Hari ini kami menyampaikan sedikit materi tentang penggunaan memori yang kompeten di Android .



Selamat membaca!

Artikel ini berfokus pada teknik dasar untuk mengelola penggunaan memori dalam aplikasi - misalnya, browser, editor foto, dan pemirsa PDF - di mana permintaan memori besar dibuat.

Pertama, sedikit teori


Sebagian besar aplikasi Android berjalan di atas runtime ( ART ), yang telah menggantikan mesin virtual Dalvik yang sudah usang. ART dan Dalvik serupa dengan Java Virtual Machine (JVM), yang dengannya mereka berbagi prinsip desain yang serupa. Mereka menggunakan dua ruang terpisah untuk menyimpan data aplikasi: tumpukan dan tumpukan.

Stack-memory

Stack-memory di Java digunakan untuk menyimpan variabel lokal (tipe primitif dan referensi objek). Setiap utas Java memiliki tumpukan terpisah. Memori tumpukan relatif kecil dibandingkan dengan memori tumpukan. Ukuran tumpukan Java Dalvik biasanya 32 KB untuk kode Java dan 1 MB untuk kode asli (C ++ / JNI). Tumpukan terpadu untuk Java dan C ++ telah muncul dalam ART, ukurannya sekitar 1 MB.

Ketika aplikasi memilih seluruh memori stack hingga batasnya, kesalahan terjadi StackOverflowError. Alasan paling mungkin batas tumpukan dapat dicapai adalah rekursi tak terbatas atau pemanggilan metode yang terlalu dalam. Referensi ke memori tumpukan selalu dibuat dalam urutan LIFO (last come - first served). Setiap kali suatu metode dipanggil, frame baru didorong ke stack dengan variabel lokal dari metode ini. Ketika metode selesai, frame-nya dikeluarkan dari stack, dan setiap nilai yang dihasilkan kemungkinan dikirim kembali ke stack. Jadi, masalah pertama (rekursi tak terbatas) adalah bug yang mudah untuk diperbaiki, tetapi yang kedua membutuhkan beberapa refactoring, yang terdiri dari penggelaran pemanggilan metode rekursif dan mengubahnya menjadi satu lingkaran.

Tumpukan memori

Heap memory di Java digunakan oleh mesin virtual untuk mengalokasikan objek. Setiap kali sebuah objek dibuat, itu terjadi di heap. Mesin virtual, seperti JVM atau ART, secara teratur mengumpulkan sampah, menghapus semua objek yang tidak lagi dirujuk, dan dengan demikian membebaskan memori untuk mengalokasikan objek baru.
Untuk memastikan kegunaan, Android dengan ketat membatasi ukuran tumpukan untuk setiap aplikasi yang berjalan. Batas ukuran tumpukan bervariasi dari perangkat ke perangkat dan tergantung pada berapa banyak RAM pada perangkat itu. Jika aplikasi Anda mencapai ukuran tumpukan maksimum dan mencoba mengalokasikan lebih banyak memori, kesalahan dihasilkan OutOfMemoryErrordan aplikasi berakhir. Mari kita lihat beberapa contoh untuk membantu menghindari situasi ini.

Analisis memori tumpukan


Alat paling penting untuk memahami masalah memori dalam aplikasi Anda dan memahami bagaimana memori digunakan adalah profiler memori yang tersedia di Android Studio.

Alat ini memvisualisasikan berapa banyak memori yang dikonsumsi aplikasi Anda dari waktu ke waktu. Anda dapat mengambil snapshot dari tumpukan Java dalam aplikasi yang sedang berjalan, merekam operasi alokasi memori, dan melacak tumpukan atau sejarah alokasi memori ini dalam UI yang kuat.

Sesi profiler memori khas akan terlihat seperti ini:

  • Kami melihat alokasi memori dan saluran pengumpul sampah yang paling sering untuk mengidentifikasi kemungkinan masalah kinerja.
  • , , , , , . , . , , PdfActivity PSPDFKit .
  • , . , . – , , .


Pengumpul sampah modern adalah karya seni teknologi yang kompleks, hasil penelitian dan pengembangan selama bertahun-tahun, di mana ratusan orang berpartisipasi, dari akademisi hingga pengembang profesional. Namun, tetap harus waspada untuk mencegah kebocoran memori.

Solusi teladan untuk mendeteksi kebocoran memori adalah perpustakaan LeakCanary . Secara otomatis mengeluarkan notifikasi ketika di unit uji Anda (pengembangan pengembangan), memberi Anda tingkat jejak kebocoran di UI program ini. Anda dapat (dan harus) mengintegrasikannya hari ini, terutama karena itu tidak sulit!

Sangat mudah untuk memprovokasi kebocoran memori ketika bekerja dengan siklus kehidupan yang kompleks atau fragmen Android. Ini sering terjadi pada titik di mana pengembang memegang referensi kuat untuk konteks UI atau objek khusus UI lainnya di tugas latar belakang atau dalam variabel statis. Salah satu cara untuk memprovokasi penundaan tersebut adalah dengan aktif memutar perangkat saat menguji aplikasi Anda.

Kosongkan memori sebagai respons terhadap peristiwa


Android mungkin memerlukan aplikasi untuk mengalokasikan memori, atau memaksanya untuk berhenti ketika memori perlu dibebaskan untuk melakukan tugas yang lebih penting. Sebelum ini terjadi, sistem akan memungkinkan Anda untuk memberikan semua memori yang tidak Anda butuhkan. Dalam aktivitas Anda, Anda perlu mengimplementasikan antarmuka ComponentCallbacks2. Dalam hal ini, setiap kali sistem Anda kehabisan memori, panggilan akan dilakukan ke metode Anda onTrimMemory(), dan Anda akan dapat membebaskan memori atau menonaktifkan fitur yang tidak akan berfungsi dalam kondisi kekurangan memori seperti itu.

Jadi, panggilan balik seperti itu ditangani dalam aplikasi PSPDFKit. Aplikasi PSPDFKit dirancang dengan perhitungan penggunaan aktif memori untuk caching, sehingga aplikasi berjalan semulus mungkin. Awalnya, tidak diketahui berapa banyak memori yang tersedia pada perangkat, sehingga PSPDFKit beradaptasi dengan situasi dan membatasi penggunaan memori ketika menerima pemberitahuan bahwa tidak ada cukup memori. Oleh karena itu, aplikasi yang terintegrasi dengan PSPDFKit bekerja bahkan pada perangkat berteknologi rendah, tetapi dengan kinerja yang berkurang karena fakta bahwa caching dinonaktifkan.

Tumpukan besar


Salah satu solusi front-end untuk mengatasi kebutuhan memori yang tinggi adalah dengan meminta sejumlah besar Dalvik untuk aplikasi Anda. Untuk melakukan ini, Anda dapat menambahkan android:largeHeap="true"tag <aplikasi> dalam file AndroidManifest.xml.

Jika properti largeHeapdiatur ke nilai true, Android akan membuat semua proses untuk aplikasi Anda dengan tumpukan besar. Pengaturan ini hanya dimaksudkan untuk aplikasi yang, menurut sifatnya, tidak dapat bekerja tanpanya, yaitu, mereka menggunakan sumber daya yang banyak yang harus secara bersamaan masuk ke memori.

Sangat tidak disarankan untuk menggunakan tumpukan besar jika Anda hanya ingin menaikkan plafon untuk kemungkinan penggunaan memori. Penggunaan memori harus selalu dioptimalkan, karena bahkan tumpukan besar aplikasi Anda mungkin tidak cukup ketika bekerja pada perangkat yang lemah dengan memori kecil.

Periksa berapa banyak memori yang dapat digunakan aplikasi Anda


Tidak ada salahnya untuk memeriksa seberapa besar tumpukan aplikasi Anda dan untuk secara dinamis menyesuaikan kode Anda dan kemampuan yang tersedia untuk batas memori ini. Anda dapat memeriksa ukuran tumpukan maksimum langsung saat runtime menggunakan metode getMemoryClass()atau getLargeMemoryClass()(ketika tumpukan besar diaktifkan).

Android bahkan mendukung perangkat dengan RAM hanya 512 MB. Pastikan untuk tidak mengabaikan perangkat berteknologi rendah! Menggunakan metodeisLowRamDevice()Anda dapat memeriksa apakah aplikasi Anda berjalan pada perangkat seperti itu di mana tidak tersedia cukup memori. Perilaku yang tepat dari metode ini bergantung pada perangkat, tetapi biasanya mengembalikan true pada perangkat dengan kurang dari 1 GB RAM. Anda perlu memastikan bahwa aplikasi Anda berfungsi dengan baik pada perangkat ini, dan menonaktifkan semua fitur yang menggunakan banyak memori.

Baca lebih lanjut tentang cara Android bekerja pada perangkat dengan sedikit memori, Anda dapat membaca di sini ; Kiat pengoptimalan tambahan juga disediakan di sini.

Gunakan struktur data yang dioptimalkan


Dalam banyak kasus, aplikasi menggunakan terlalu banyak memori karena alasan sederhana sehingga tidak menggunakan struktur data yang paling tepat.

Koleksi Java tidak dapat menyimpan tipe primitif yang efisien dan perlu mengemas kunci dan nilainya. Misalnya, HashMapdengan kunci integer harus diganti dengan yang dioptimalkan SparseArray. Pada akhirnya, Anda selalu dapat menggunakan array mentah alih-alih koleksi, dan ini adalah ide bagus jika koleksi Anda tidak dapat diubah ukurannya.

Struktur data lain yang tidak efisien dalam hal penggunaan memori termasuk berbagai serialisasi. Ya, memang, format XML atau JSON nyaman digunakan, Anda dapat mengurangi penggunaan memori jika Anda bekerja dengan format biner yang lebih efisien, misalnya, buffer protokol.

Semua contoh ini, dengan struktur data yang dioptimalkan untuk menghemat memori, hanyalah petunjuk. Seperti refactoring, Anda harus terlebih dahulu menemukan sumber masalah, dan kemudian beralih ke optimasi kinerja tersebut.

Cegah pengocokan memori


Mesin virtual Java / Android mengalokasikan objek dengan sangat cepat. Pengumpulan sampah juga sangat cepat. Namun, ketika mengalokasikan sejumlah besar objek dalam waktu singkat, Anda mungkin menghadapi masalah yang disebut "memory churn". Dalam hal ini, mesin virtual tidak akan punya waktu untuk mengalokasikan objek pada kecepatan ini, dan pengumpul sampah akan membuangnya, dan aplikasi akan mulai melambat, dan dalam kasus-kasus ekstrem bahkan akan menggunakan semua memori.

Masalah utama pada wilayah Android dalam hal ini adalah bahwa kami tidak mengontrol kapan pengumpulan sampah akan terjadi. Secara potensial, ini dapat menyebabkan masalah: misalnya, pengumpul sampah bekerja tepat pada saat animasi dibuka di layar dan kami melebihi ambang 16 ms, yang memastikan tampilan frame yang mulus. Oleh karena itu, penting untuk mencegah alokasi memori yang berlebihan dalam kode.

Contoh situasi yang mengarah ke pengocokan memori adalah alokasi objek besar, misalnya, Cat di dalam metode onDraw()presentasi. Dalam hal ini, banyak objek dibuat dengan cepat, dan pengumpulan sampah dapat dimulai, yang dapat mempengaruhi kinerja tampilan ini. Seperti yang dinyatakan di atas, Anda harus selalu memantau penggunaan memori untuk menghindari situasi seperti itu.

Kesimpulan


Memori akses acak (RAM) pada perangkat seluler dapat menjadi sumber daya yang sangat terbatas. Memastikan penggunaan memori yang efisien dalam aplikasi sangat penting jika aplikasi Anda bekerja dengan objek yang relatif besar, misalnya, grafik raster (pemirsa PDF, browser web, editor foto) atau file media besar (editor audio atau video). Dengan mengikuti tip-tip ini, Anda akan belajar cara membuat aplikasi berkualitas tinggi yang akan bekerja pada tingkat yang dapat diterima, bahkan pada perangkat yang paling kuat.

All Articles