Mengoptimalkan penggunaan memori

Pengoptimalan memori sangat penting untuk memastikan performa yang lancar, mencegah aplikasi error, serta menjaga stabilitas sistem dan kondisi platform. Meskipun penggunaan memori harus dipantau dan dioptimalkan di setiap aplikasi, aplikasi konten untuk perangkat TV memiliki tantangan khusus yang berbeda dari aplikasi Android biasa untuk perangkat genggam.

Konsumsi memori yang tinggi dapat menyebabkan masalah pada perilaku aplikasi dan sistem, termasuk:

  • Aplikasi itu sendiri dapat menjadi lambat atau tertunda, atau dalam kasus terburuk, ditutup.
  • Layanan sistem yang terlihat oleh pengguna (Dasbor Kontrol Volume, Setelan Gambar, Asisten Suara, dll.) menjadi sangat lambat atau mungkin tidak berfungsi sama sekali.
  • Proses daemon low memory killer (LMK) dapat bereaksi terhadap tekanan memori yang tinggi dengan menghentikan proses yang paling tidak penting; lalu komponen ini dapat dimulai ulang segera setelahnya, memicu lonjakan pertentangan sumber daya lebih lanjut yang dapat secara langsung memengaruhi aplikasi latar depan.
  • Transisi ke Peluncur dapat tertunda secara signifikan, dan membuat aplikasi latar depan tampak tidak responsif hingga transisi selesai.
  • Sistem dapat mulai menggunakan pengklaiman langsung, menghentikan sementara eksekusi thread saat menunggu alokasi memori. Hal ini dapat terjadi pada thread apa pun seperti thread utama atau thread terkait codec yang berpotensi menyebabkan penurunan frame audio dan video, serta gangguan UI.

Pertimbangan memori di Perangkat TV

Perangkat TV biasanya memiliki memori yang jauh lebih kecil daripada ponsel atau tablet. Misalnya, konfigurasi yang dapat kita lihat di TV adalah RAM 1 GB dan resolusi video 1080p. Pada saat yang sama, sebagian besar aplikasi TV memiliki fitur yang serupa; oleh karena itu, implementasi dan tantangan yang dihadapi juga serupa. Kedua situasi ini menimbulkan masalah yang tidak terlihat pada jenis dan aplikasi perangkat lain:

  • Aplikasi TV media biasanya terdiri dari tampilan gambar dalam petak dan gambar latar layar penuh yang memerlukan pemuatan banyak gambar ke dalam memori dalam waktu singkat
  • Aplikasi TV memutar streaming multimedia yang memerlukan alokasi sejumlah memori tertentu untuk memutar video dan audio serta memerlukan buffer media yang cukup besar untuk memastikan pemutaran yang lancar.
  • Fitur media tambahan (pencarian, perubahan episode, perubahan trek audio, dll.) dapat memberikan tekanan memori tambahan jika tidak diterapkan dengan benar.

Memahami perangkat TV

Panduan ini terutama berfokus pada penggunaan memori aplikasi dan target memori untuk perangkat RAM rendah.

Di perangkat TV, pertimbangkan karakteristik berikut:

  • Memori perangkat: Jumlah Random Access Memory (RAM) yang diinstal perangkat.
  • Resolusi UI perangkat: Resolusi yang digunakan perangkat untuk merender UI OS dan Aplikasi; resolusi ini biasanya lebih rendah daripada resolusi video perangkat.
  • Resolusi video: Resolusi maksimum yang dapat digunakan perangkat untuk memutar video.

Hal ini menyebabkan pengategorian berbagai jenis perangkat dan cara penggunaan memori oleh perangkat tersebut.

Ringkasan perangkat TV

Memori perangkat Resolusi video perangkat Resolusi UI perangkat isLowRAMDevice()
1 GB 1080p 720p Ya
1,5 GB 2160p 1080p Ya
≥1,5 GB 1080p 720p atau 1080p Tidak*
≥2 GB 2160p 1080p Tidak*

Perangkat TV dengan RAM rendah

Perangkat ini berada dalam situasi dengan keterbatasan memori dan akan melaporkan ActivityManager.isLowRAMDevice() ke benar (true). Aplikasi yang berjalan di perangkat TV dengan RAM rendah perlu menerapkan langkah-langkah kontrol memori tambahan.

Kami menganggap perangkat dengan karakteristik berikut termasuk dalam kategori ini:

  • Perangkat 1 GB: RAM 1 GB, resolusi UI 720p/HD (1280x720), Resolusi Video 1080p/FullHD (1920x1080)
  • Perangkat 1,5 GB: RAM 1,5 GB, resolusi UI 1080p/FullHD (1920x1080), resolusi Video 2160p/UltraHD/4K (3840x2160)
  • Situasi lain saat OEM menentukan tanda ActivityManager.isLowRAMDevice() karena batasan memori tambahan.

Perangkat TV biasa

Perangkat ini tidak mengalami situasi tekanan memori yang signifikan. Kami menganggap perangkat ini memiliki karakteristik berikut:

  • RAM ≥1,5 GB, UI 720p atau 1080p, dan resolusi video 1080p
  • RAM ≥2 GB, UI 1080p, dan resolusi video 1080p atau 2160p

Hal ini tidak berarti aplikasi tidak perlu memperhatikan penggunaan memori di perangkat ini, karena beberapa penyalahgunaan memori tertentu masih dapat menghabiskan memori yang tersedia dan berperforma buruk.

Target memori di perangkat TV dengan RAM rendah

Saat mengukur memori di perangkat ini, kami sangat menyarankan untuk memantau setiap bagian memori menggunakan profiler memori Android Studio. Aplikasi TV harus memprofilkan penggunaan memori dan berupaya menempatkan kategorinya di bawah nilai minimum yang kami tetapkan di bagian ini.

Memory Profiler

Di bagian Cara penghitungan memori, Anda akan menemukan penjelasan mendetail tentang angka memori yang dilaporkan. Untuk definisi nilai minimum untuk aplikasi TV, kami akan berfokus pada tiga kategori memori:

  • Anonim + Swap: Terdiri dari memori alokasi Java + Native + Stack di Android Studio.
  • Grafis: Dilaporkan langsung di alat profiler. Umumnya terdiri dari tekstur grafis.
  • File: Dilaporkan sebagai kategori "Kode" + "Lainnya" di Android Studio.

Dengan definisi ini, tabel berikut menunjukkan nilai maksimum yang harus digunakan setiap jenis grup memori:

Jenis memori Tujuan Target penggunaan (1 GB)
Anonim + Swap (Java + Native + Stack) Digunakan untuk alokasi, buffer media, variabel, dan tugas berat lainnya yang menggunakan banyak memori. < 160 MB
Grafik Digunakan oleh GPU untuk tekstur dan buffer terkait tampilan 30-40 MB
File Digunakan untuk halaman kode dan file dalam memori. 60-80 MB

Total memori maksimum (Anon+Swap + Grafis + File) tidak boleh melebihi berikut ini:

  • Penggunaan total memori 280 MB (Anon+Swap + Grafis + File) untuk perangkat RAM rendah 1 GB.

Sangat disarankan untuk tidak melebihi:

  • Penggunaan memori 200 MB pada (Anon+Swap + Grafis).

Memori file

Sebagai panduan umum untuk memori yang didukung file, perhatikan bahwa:

  • Secara umum, memori file ditangani dengan baik oleh pengelolaan memori OS.
  • Saat ini kami belum menemukan bahwa hal ini menjadi penyebab utama tekanan memori.

Namun, saat menangani Memori file secara umum:

  • Jangan sertakan library yang tidak digunakan ke dalam build Anda, dan gunakan subset kecil library, bukan library lengkap jika memungkinkan.
  • Jangan biarkan file besar tetap dibuka ke dalam memori dan lepaskan segera setelah Anda selesai menggunakannya.
  • Minimalkan ukuran kode yang dikompilasi untuk class Java dan Kotlin, lihat panduan Menyingkat, meng-obfuscate, dan mengoptimalkan aplikasi Anda.

Rekomendasi TV tertentu

Bagian ini memberikan rekomendasi khusus untuk mengoptimalkan penggunaan memori di perangkat TV.

Memori grafis

Gunakan format dan resolusi gambar yang sesuai.

  • Jangan memuat gambar dengan resolusi yang lebih tinggi daripada resolusi UI perangkat. Misalnya, gambar 1080p harus dikecilkan menjadi 720p di perangkat UI 720p.
  • Gunakan bitmap yang didukung hardware jika memungkinkan.
    • Pada library seperti Glide, aktifkan fitur Downsampler.ALLOW_HARDWARE_CONFIG yang dinonaktifkan secara default. Mengaktifkan opsi ini akan menghindari duplikasi bitmap yang seharusnya berada di memori grafis dan memori anonim.
  • Hindari rendering dan rendering ulang perantara
    • Masalah ini dapat diidentifikasi dengan Android GPU Inspector:
    • Lihat di bagian "Tekstur" untuk menemukan gambar yang merupakan langkah-langkah menuju render akhir, bukan hanya elemen yang membentuknya. Gambar ini biasanya disebut "render menengah".
    • Untuk aplikasi Android SDK, Anda sering kali dapat menghapusnya dengan menggunakan flag tata letak forceHasOverlappedRendering:false untuk menonaktifkan render perantara untuk tata letak ini.
    • Lihat Menghindari Rendering yang Tumpang-Tindih pada rendering yang tumpang-tindih sebagai referensi yang bagus.
  • Hindari memuat gambar placeholder jika memungkinkan, gunakan @android:color/ atau @color untuk tekstur placeholder.
  • Hindari menggabungkan beberapa gambar di perangkat saat komposisi dapat dilakukan secara offline. Lebih memilih memuat gambar mandiri daripada melakukan komposisi gambar dari gambar yang didownload
  • Ikuti panduan Menangani bitmap untuk menangani Bitmap dengan lebih baik.

Memori Anon+Swap

Anon+Swap terdiri dari alokasi Native + Java + Stack di profiler memori Android Studio. Gunakan ActivityManager.isLowMemoryDevice() untuk memeriksa apakah perangkat memiliki batasan memori, dan beradaptasi dengan situasi ini dengan mengikuti panduan berikut.

  • Media:
    • Tentukan ukuran variabel untuk buffer media, bergantung pada RAM perangkat dan resolusi pemutaran video. Ini akan memperhitungkan pemutaran video selama 1 menit:
      1. 40-60 MB untuk 1 GB / 1080p
      2. 60-80 MB untuk 1,5 GB / 1080p
      3. 80-100 MB untuk 1,5 GB / 2160p
      4. 100-120 MB untuk 2 GB / 2160p
    • Membebaskan alokasi memori media saat mengubah episode untuk mencegah peningkatan jumlah total memori Anonim.
    • Segera lepaskan dan hentikan resource media saat aplikasi Anda dihentikan: Gunakan callback siklus proses aktivitas untuk menangani resource audio dan video. Jika Anda bukan aplikasi audio, hentikan pemutaran saat onStop() terjadi pada aktivitas Anda, simpan semua pekerjaan yang sedang Anda lakukan, dan tetapkan resource Anda untuk dilepaskan. Untuk menjadwalkan tugas yang mungkin Anda perlukan nanti. Lihat bagian Jobs and Alarms.
    • Perhatikan memori buffer saat mencari video: Developer sering kali mengalokasikan konten tambahan 15-60 detik ke depan saat mencari agar video siap untuk pengguna, tetapi hal ini menciptakan overhead memori tambahan. Secara umum, jangan mengambil buffer masa depan lebih dari 5 detik hingga pengguna memilih posisi video baru. Jika Anda benar-benar perlu melakukan pra-penyangga waktu tambahan saat mencari, pastikan untuk:
      • Alokasikan buffer pencarian sebelumnya dan gunakan kembali.
      • Ukuran buffer tidak boleh lebih besar dari 15-25 MB (bergantung pada memori perangkat).
  • Alokasi:
    • Gunakan panduan memori grafis untuk memastikan Anda tidak menduplikasi gambar di Memori anonim
      • Gambar sering kali menjadi pengguna memori terbesar sehingga duplikasi gambar dapat memberikan banyak tekanan pada perangkat. Hal ini terutama berlaku selama navigasi berat pada tampilan petak gambar.
    • Lepaskan alokasi dengan menghilangkan referensinya saat berpindah layar: Pastikan tidak ada referensi ke bitmap dan objek yang tertinggal.
  • Library:
    • Profil alokasi memori dari library saat menambahkan yang baru, karena library tersebut juga dapat memuat library tambahan, yang juga dapat membuat alokasi dan membuat Binding.
  • Jaringan:
    • Jangan melakukan panggilan jaringan pemblokiran selama startup aplikasi, karena akan memperlambat waktu startup aplikasi dan membuat overhead memori tambahan saat peluncuran, saat memori sangat dibatasi oleh pemuatan aplikasi. Tampilkan layar pemuatan atau layar pembuka terlebih dahulu dan lakukan permintaan jaringan setelah UI tersedia.

Binding

Pengikatan memperkenalkan overhead memori tambahan karena membawa aplikasi lain ke dalam memori atau meningkatkan konsumsi memori aplikasi yang terikat (jika sudah ada dalam memori sebelumnya) untuk memfasilitasi panggilan API. Akibatnya, mengurangi ketersediaan memori untuk aplikasi latar depan. Saat mengikat layanan, perhatikan kapan dan berapa lama Anda menggunakan pengikatan. Pastikan untuk melepaskan binding segera setelah tidak diperlukan.

Pengikatan umum dan praktik terbaik:

  • Play Integrity API: Digunakan untuk memeriksa integritas perangkat
    • Periksa integritas perangkat setelah layar pemuatan dan sebelum pemutaran media
    • Lepaskan referensi ke PlayIntegrity StandardIntegrityManager sebelum memutar konten.
  • Play Billing Library: Digunakan untuk mengelola langganan dan pembelian menggunakan Google Play
  • GMS FontsProvider
    • Sebaiknya gunakan font mandiri di perangkat dengan RAM rendah daripada menggunakan penyedia font, karena mendownload font memerlukan biaya yang besar dan FontsProvider akan mengikat layanan untuk melakukannya.
  • Library Asisten Google: Terkadang digunakan untuk penelusuran dan penelusuran dalam aplikasi. Jika memungkinkan, ganti library ini.
    • Untuk aplikasi leanback: Gunakan text-to-speech Gboard atau library androidx.leanback.
      • Ikuti panduan Penelusuran untuk menerapkan penelusuran.
      • Catatan: leanback tidak digunakan lagi dan aplikasi harus beralih ke TV Compose.
    • Untuk aplikasi Compose:
      • Gunakan fitur text-to-speech Gboard untuk menerapkan penelusuran suara.
    • Terapkan Tonton Berikutnya agar konten media di aplikasi Anda dapat ditemukan.

Layanan Latar Depan

Layanan Latar Depan adalah jenis layanan khusus yang terkait dengan notifikasi. Notifikasi ini ditampilkan di area notifikasi di ponsel dan tablet, tetapi perangkat TV tidak memiliki area notifikasi seperti perangkat tersebut. Meskipun Layanan Latar Depan berguna karena dapat terus berjalan saat aplikasi berada di latar belakang, aplikasi TV harus mengikuti panduan berikut:

Di Android TV dan Google TV, Layanan Latar Depan hanya diizinkan untuk tetap berjalan setelah pengguna keluar dari aplikasi:

  • Untuk aplikasi audio: Layanan Latar Depan hanya diizinkan untuk terus berjalan setelah pengguna keluar dari aplikasi agar dapat terus memutar trek audio. Layanan harus segera dihentikan setelah pemutaran audio berakhir.
  • Untuk aplikasi lain: Semua Layanan Latar Depan harus dihentikan. setelah pengguna keluar dari aplikasi Anda, karena tidak ada notifikasi untuk memberi tahu pengguna bahwa aplikasi masih berjalan dan menggunakan resource.
  • Untuk tugas latar belakang seperti memperbarui rekomendasi atau Tonton Berikutnya, gunakan WorkManager.

Tugas dan Alarm

WorkManager adalah Android API canggih untuk menjadwalkan tugas berulang di latar belakang. WorkManager akan menggunakan JobScheduler baru jika tersedia (SDK 23+) dan AlarmManager lama jika tidak tersedia. Untuk praktik terbaik dalam menjalankan tugas terjadwal di TV, ikuti rekomendasi berikut:

  • Hindari penggunaan API AlarmManager, di SDK 23+, terutama AlarmManager.set(), AlarmManager.setExact() dan metode serupa, karena tidak memungkinkan sistem memutuskan waktu yang tepat untuk menjalankan tugas (misalnya, saat perangkat dalam kondisi tidak ada aktivitas).
  • Di perangkat dengan RAM rendah, hindari menjalankan tugas kecuali jika benar-benar diperlukan. Jika perlu, gunakan WorkManager WorkRequest hanya untuk memperbarui rekomendasi setelah pemutaran, dan coba lakukan saat aplikasi masih terbuka.
  • Tentukan Constraints WorkManager agar sistem menjalankan tugas Anda pada waktu yang tepat:

Kotlin

Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresStorageNotLow(true)
    .setRequiresDeviceIdle(true)
    .build()

Java

Constraints.Builder()
    .setRequiredNetworkType(NetworkType.CONNECTED)
    .setRequiresStorageNotLow(true)
    .setRequiresDeviceIdle(true)
    .build()
  • Jika Anda harus menjalankan tugas secara rutin (misalnya, untuk memperbarui Tonton Berikutnya berdasarkan aktivitas menonton konten pengguna di aplikasi Anda di perangkat lain), maka jaga penggunaan memori agar tetap rendah dengan menjaga konsumsi memori tugas di bawah 30 MB.

Pertimbangan memori umum

Pedoman berikut memberikan informasi umum tentang pengembangan Aplikasi Android:

  • Minimalkan alokasi objek, optimalkan penggunaan ulang objek, dan batalkan alokasi objek yang tidak digunakan dengan segera.
    • Jangan menyimpan referensi ke objek, terutama bitmap.
    • Hindari penggunaan System.gc() dan panggilan memori rilis langsung karena mengganggu proses penanganan memori sistem: Sebagai contoh, di perangkat yang menggunakan zRAM, panggilan paksa ke gc() dapat meningkatkan penggunaan memori untuk sementara karena kompresi dan dekompresi memori.
    • Gunakan LazyList seperti yang ditunjukkan dalam browser katalog di Compose atau RecyclerView di toolkit UI Leanback yang kini tidak digunakan lagi untuk menggunakan kembali tampilan dan tidak membuat ulang elemen daftar.
    • Simpan secara lokal elemen yang dibaca dari penyedia konten eksternal yang kemungkinan tidak akan berubah dan tentukan interval pembaruan yang mencegah alokasi memori eksternal tambahan.
  • Periksa kemungkinan kebocoran memori.
    • Waspadai kasus kebocoran memori umum seperti referensi di dalam thread anonim, realokasi buffer video yang tidak pernah dilepaskan, dan situasi serupa lainnya.
    • Gunakan heap dump untuk men-debug kebocoran memori.
  • Buat profil dasar pengukuran untuk meminimalkan jumlah kompilasi tepat waktu yang diperlukan saat menjalankan aplikasi Anda pada cold start.

Memahami pengembalian memori langsung

Saat aplikasi Android TV meminta memori dan sistem sedang tertekan, kernel Linux, yang mendasari Android, mungkin harus menggunakan pengambilan kembali memori langsung.

Proses ini melibatkan penghentian sementara semua thread yang mengalokasikan sepenuhnya untuk menunggu halaman memori yang dikosongkan. Hal ini terjadi saat pengklaiman latar belakang tidak dapat mempertahankan kumpulan memori yang cukup secara proaktif.

Hal ini dapat menyebabkan jeda atau jank yang terlihat jelas dalam pengalaman pengguna karena sistem menjeda alokasi thread hingga memori yang tersedia mencukupi. Dalam hal ini, alokasi thread tidak terbatas pada panggilan kode aplikasi seperti malloc(); memori perlu dialokasikan ke halaman di halaman kode, misalnya.

Ringkasan alat