Mengoptimalkan download untuk akses jaringan yang efisien

Penggunaan radio nirkabel untuk mentransfer data berpotensi menjadi salah satu sumber konsumsi baterai paling signifikan pada aplikasi Anda. Untuk meminimalkan konsumsi baterai akibat aktivitas jaringan, Anda perlu memahami bagaimana model konektivitas Anda akan memengaruhi hardware radio yang mendasarinya.

Pelajaran ini memperkenalkan Anda dengan mesin status radio nirkabel dan menjelaskan bagaimana model konektivitas aplikasi Anda berinteraksi dengannya. Akan dibahas juga cara meminimalkan koneksi data, penggunaan prefetching, dan pemaketan transfer untuk meminimalkan konsumsi baterai akibat transfer data.

Mesin status radio

Radio nirkabel yang sepenuhnya aktif mengonsumsi daya yang signifikan, sehingga radio dapat beralih dari satu status energi ke status lainnya untuk menghemat daya saat tidak digunakan, sekaligus berupaya meminimalkan latensi yang terkait dengan "penyalaan" radio saat diperlukan.

Mesin status untuk radio jaringan 3G standar terdiri dari tiga status energi:

  1. Daya penuh: Digunakan saat koneksi aktif, memungkinkan perangkat mentransfer data pada tingkat tertinggi yang dimungkinkan.
  2. Daya rendah: Status antara, menggunakan sekitar 50% daya baterai dalam keadaan penuh.
  3. Siaga: Status energi minimal saat tidak ada koneksi jaringan yang aktif atau saat koneksi jaringan tidak diperlukan.

Meskipun mengonsumsi daya baterai jauh lebih sedikit, status rendah dan siaga juga menimbulkan latensi yang signifikan terhadap permintaan jaringan. Diperlukan waktu sekitar 1,5 detik untuk mengembalikan status energi dari daya rendah ke daya penuh, dan lebih dari 2 detik dari siaga ke daya penuh.

Untuk meminimalkan latensi, mesin status menerapkan penundaan untuk menunda transisi ke status energi yang lebih rendah. Gambar 1 menggunakan pengaturan waktu AT&T untuk radio 3G standar.

Gambar 1. Mesin status radio nirkabel 3G standar.

Mesin status radio pada setiap perangkat, terutama penundaan transisi ("tail time") dan latensi pengaktifan yang terkait, akan bervariasi bergantung pada teknologi radio nirkabel yang digunakan (2G, 3G, LTE, dll.) serta ditentukan dan dikonfigurasi oleh operator jaringan tempat perangkat beroperasi.

Pelajaran ini menjelaskan mesin status yang representatif untuk radio nirkabel 3G standar, berdasarkan data yang disediakan oleh AT&T. Namun, prinsip umum dan praktik terbaik yang dihasilkan berlaku untuk semua implementasi radio nirkabel.

Pendekatan ini sangat efektif untuk penjelajahan web standar karena mencegah latensi yang tidak diinginkan saat pengguna menjelajah web. Tail-time yang relatif rendah juga memastikan bahwa begitu sesi penjelajahan selesai, radio dapat beralih ke tingkat energi yang lebih rendah.

Sayangnya, pendekatan ini dapat mengakibatkan aplikasi yang tidak efisien pada OS smartphone modern seperti Android, di mana aplikasi berjalan di latar depan (latensi penting) dan juga di latar belakang (masa pakai baterai harus diprioritaskan).

Cara Aplikasi Memengaruhi Mesin Status Radio

Setiap kali Anda membuat sambungan jaringan baru, radio beralih ke status daya penuh. Dalam kasus mesin status radio 3G standar yang dijelaskan di atas, radio akan tetap berada dalam daya penuh sepanjang durasi transfer—plus tambahan tail-time 5 detik—diikuti 12 detik pada status energi rendah. Jadi, untuk perangkat 3G standar, setiap sesi transfer data akan menyebabkan radio menarik energi selama hampir 20 detik.

Dalam praktiknya, hal ini berarti aplikasi yang mentransfer data tidak terpaket selama 1 detik setiap 18 detik akan membuat radio nirkabel aktif terus-menerus, dan baru mengalihkannya ke daya tinggi saat radio hendak memasuki mode siaga. Akibatnya, setiap menit radio akan mengonsumsi daya baterai pada status daya tinggi selama 18 detik, dan pada status daya rendah selama 42 detik sisanya.

Sebagai perbandingan, aplikasi yang sama yang mentransfer data terpaket selama 3 detik setiap menit akan membuat radio tetap berada dalam status daya tinggi selama 8 detik saja, dan akan bertahan dalam status daya rendah selama 12 detik setelahnya.

Contoh kedua ini memungkinkan radio untuk berada dalam status siaga selama 40 detik setiap menitnya, sehingga menghasilkan pengurangan signifikan dalam konsumsi daya baterai.

Gambar 2. Perbandingan penggunaan daya radio nirkabel untuk transfer data terpaket vs tidak terpaket.

Mem-prefetch data

Prefetching data adalah cara efektif untuk mengurangi jumlah sesi transfer data independen. Dengan prefetching, Anda dapat mendownload semua data yang kemungkinan akan Anda perlukan selama jangka waktu tertentu dalam sekali burst, melalui satu koneksi, pada kapasitas penuh.

Dengan memuat transfer di awal, Anda mengurangi jumlah aktivasi radio yang diperlukan untuk mendownload data. Hasilnya, Anda tidak hanya menghemat masa pakai baterai, tetapi juga mengurangi latensi, menurunkan bandwidth yang diperlukan, dan mengurangi waktu download.

Prefetching juga memberikan pengalaman pengguna yang lebih baik dengan meminimalkan latensi dalam aplikasi yang disebabkan oleh menunggu selesainya proses download sebelum menjalankan suatu tindakan atau menampilkan data.

Namun, jika digunakan terlalu agresif, prefetching menghadirkan risiko berupa meningkatnya konsumsi daya baterai dan penggunaan bandwidth—serta kuota download—dengan mendownload data yang tidak digunakan. Anda juga harus memastikan bahwa prefetching tidak menunda pengaktifan aplikasi selagi aplikasi tersebut menunggu prefetching selesai. Dalam praktiknya, hal itu dapat berarti data akan diproses secara progresif, atau inisiasi transfer berurutan diprioritaskan sedemikian rupa sehingga data yang diperlukan untuk pengaktifan aplikasi didownload dan diproses terlebih dahulu.

Seberapa agresif Anda menggunakan prefetching bergantung pada ukuran data yang didownload dan kemungkinan penggunaan data tersebut. Sebagai panduan kasar, berdasarkan mesin status yang dijelaskan di atas, untuk data yang memiliki kemungkinan digunakan 50% dalam sesi pengguna saat ini, biasanya Anda dapat melakukan prefetching selama sekitar 6 detik (sekitar 1-2 Mb) sebelum potensi biaya dari mendownload data yang tidak digunakan dapat mengimbangi potensi penghematan dari tidak mendownload data tersebut.

Secara umum, sebaiknya prefetch data sedemikian rupa sehingga Anda hanya perlu menginisiasi download baru setiap 2 hingga 5 menit, dan dalami urutan 1 hingga 5 megabyte.

Dengan mengikuti prinsip ini, download berukuran besar—seperti file video—sebaiknya dilakukan sebagai potongan-potongan dalam interval yang teratur (setiap 2 hingga 5 menit), sehingga secara efektif Anda hanya mem-prefetch data video yang kemungkinan akan ditonton dalam beberapa menit berikutnya.

Perlu diketahui bahwa download selanjutnya harus dipaketkan, seperti yang dijelaskan di bagian Membuat Batch Transfer dan Koneksi, dan bahwa perkiraan ini akan bervariasi menurut jenis dan kecepatan koneksi, seperti yang dibahas dalam Mengubah Pola Download Berdasarkan Jenis Konektivitas.

Mari kita lihat beberapa contoh praktis berikut:

Pemutar musik

Anda dapat mem-prefetch seluruh album, tetapi jika pengguna berhenti mendengarkan setelah lagu pertama, berarti Anda telah membuang banyak bandwidth dan masa pakai baterai.

Pendekatan yang lebih baik adalah mempertahankan buffer satu lagu selain lagu yang sedang diputar. Untuk streaming musik, daripada mempertahankan aliran kontinu yang membuat radio tetap aktif sepanjang waktu, cobalah menggunakan HTTP live streaming untuk mentransmisikan streaming audio dalam beberapa burst, serupa dengan pendekatan prefetching yang dijelaskan di atas.

Aplikasi pembaca berita

Banyak aplikasi berita berupaya mengurangi penggunaan bandwidth dengan mendownload headline hanya setelah suatu kategori dipilih, artikel lengkap hanya setelah pengguna memilih untuk membacanya, dan thumbnail tepat saat mereka men-scroll tampilan.

Dengan pendekatan ini, radio akan dipaksa untuk tetap aktif sepanjang sebagian besar sesi membaca pengguna, selama mereka men-scroll headline, berpindah kategori, dan membaca artikel. Selain itu, peralihan terus-menerus antara beberapa status energi akan mengakibatkan latensi signifikan saat pengguna beralih kategori atau membaca artikel.

Pendekatan yang lebih baik adalah mem-prefetch sejumlah data yang wajar pada saat pengaktifan, lalu mulai dengan menampilkan sekumpulan headline dan thumbnail berita teratas—agar latensi selama pengaktifan tetap rendah—dan lanjutkan dengan judul dan thumbnail sisanya, serta teks artikel untuk setiap artikel yang tersedia dari setidaknya daftar headline utama.

Alternatif lainnya adalah mem-prefetch setiap headline, thumbnail, teks artikel, dan bahkan mungkin gambar artikel lengkap—biasanya di latar belakang pada jadwal yang telah ditentukan. Pendekatan ini berisiko mengonsumsi bandwidth dan daya baterai secara signifikan untuk mendownload konten yang tidak benar-benar digunakan, sehingga sebaiknya diimplementasikan dengan hati-hati.

Salah satu solusinya adalah menjadwalkan agar download lengkap berjalan hanya saat perangkat tersambung ke Wi-Fi, dan mungkin hanya saat perangkat sedang diisi dayanya. Hal ini dibahas lebih mendetail dalam Mengubah Pola Download Berdasarkan Jenis Konektivitas.

Membuat batch transfer dan koneksi

Setiap kali Anda memulai koneksi—berapa pun ukuran transfer data yang terkait—Anda berpotensi membuat radio mengambil daya selama hampir 20 detik saat menggunakan radio nirkabel 3G standar.

Aplikasi yang mem-ping server setiap 20 detik, hanya untuk mengonfirmasi bahwa aplikasi sedang berjalan dan terlihat oleh pengguna, akan membuat radio tetap aktif tanpa batas waktu, yang berarti menimbulkan biaya baterai yang signifikan untuk transfer data yang sebenarnya hampir tidak ada.

Di sinilah pentingnya memaketkan transfer data dan membuat antrean untuk transfer yang tertunda. Jika dilakukan dengan benar, Anda dapat secara efektif memindahkan beberapa transfer yang akan terjadi ke dalam rentang waktu yang sama sehingga semuanya ditransfer bersamaan. Hal ini untuk memastikan bahwa radio menggunakan daya untuk durasi sesingkat mungkin.

Filosofi yang mendasari pendekatan ini adalah mentransfer sebanyak mungkin data pada setiap sesi transfer untuk membatasi jumlah sesi yang diperlukan.

Hal itu berarti Anda perlu membuat batch transfer dengan memasukkan transfer yang dapat menoleransi keterlambatan ke dalam antrean, dan menghentikan update dan prefetching terjadwal, sehingga operasi ini dijalankan saat transfer yang sensitif waktu diperlukan. Demikian pula, update terjadwal dan prefetching reguler harus memulai eksekusi antrean transfer yang tertunda.

Untuk contoh praktis, mari kita lihat kembali contoh sebelumnya dari Mem-prefetch Data.

Misalkan aplikasi berita yang menggunakan rutinitas prefetching yang dijelaskan di atas. Aplikasi pembaca berita mengumpulkan informasi analisis untuk memahami pola membaca pengguna dan memeringkatkan artikel yang paling populer. Agar berita tetap segar, aplikasi memeriksa ketersediaan update setiap jam. Untuk menghemat bandwidth, bukannya mendownload foto lengkap untuk setiap artikel, aplikasi hanya mem-prefetch thumbnail dan mendownload foto lengkap hanya jika foto dipilih.

Dalam contoh ini, semua informasi analisis yang terkumpul dalam aplikasi perlu dipaketkan bersama dan diantrekan untuk didownload, bukannya dikirim begitu terkumpul. Paket yang dihasilkan sebaiknya ditransfer saat foto berukuran penuh sedang didownload, atau saat update per jam sedang dilakukan.

Semua transfer yang sensitif waktu atau sesuai permintaan—seperti mendownload gambar ukuran penuh—akan menghentikan update terjadwal. Update terencana ini sebaiknya dijalankan bersamaan dengan transfer berdasarkan permintaan, dengan update berikutnya dijadwalkan terjadi setelah interval yang ditetapkan. Pendekatan ini dapat mengurangi biaya yang timbul dari melakukan update rutin dengan membonceng pada download foto sensitif waktu yang diperlukan.

Mengurangi koneksi

Secara umum, menggunakan kembali koneksi jaringan yang ada akan lebih efisien dibandingkan memulai koneksi baru. Penggunaan kembali koneksi juga memungkinkan jaringan bereaksi lebih efektif terhadap kongesti dan masalah data jaringan terkait.

Daripada membuat beberapa koneksi simultan untuk mendownload data, atau merangkai beberapa permintaan GET yang berurutan, sebaiknya Anda memaketkan permintaan tersebut menjadi GET tunggal, jika memungkinkan.

Misalnya, akan lebih efisien untuk membuat satu permintaan untuk setiap artikel berita yang akan ditampilkan dalam satu permintaan/respons daripada membuat beberapa kueri untuk beberapa kategori berita. Radio nirkabel harus berada dalam status aktif agar dapat mengirimkan paket penghentian/konfirmasi penghentian yang terkait dengan waktu tunggu server dan klien. Karena itu, sebaiknya tutup koneksi saat tidak sedang digunakan, bukannya menunggu hingga waktu tunggunya habis.

Meskipun begitu, menutup koneksi terlalu dini dapat mencegahnya digunakan kembali, sehingga kemudian diperlukan overhead tambahan untuk membuat koneksi baru. Kompromi yang baik adalah tidak menutup koneksi dengan seketika, melainkan menutupnya sebelum waktu tunggunya habis.

Mengidentifikasi masalah dengan Profiler Jaringan

Gunakan Profiler Jaringan untuk melacak kapan aplikasi Anda membuat permintaan jaringan. Anda dapat memantau bagaimana dan kapan aplikasi Anda mentransfer data dan mengoptimalkan kode yang mendasarinya dengan tepat.

Gambar 3 menunjukkan pola transfer sejumlah kecil data dalam interval sekitar 15 detik, yang menunjukkan bahwa efisiensi dapat ditingkatkan secara dramatis dengan mem-prefetch setiap permintaan atau memaketkan upload.

Gambar 3. Melacak penggunaan jaringan.

Dengan memantau frekuensi transfer data Anda, dan jumlah data yang ditransfer selama setiap koneksi, Anda dapat mengidentifikasi area dalam aplikasi yang dapat dibuat lebih hemat baterai. Secara umum, Anda perlu menemukan lonjakan singkat yang dapat ditunda, atau yang dapat menyebabkan transfer selanjutnya di-preempt.

Untuk mengidentifikasi penyebab lonjakan transfer secara lebih mendetail, Traffic Stats API memungkinkan Anda menambahkan tag ke transfer data yang terjadi dalam sebuah thread menggunakan metode TrafficStats.setThreadStatsTag(), diikuti dengan memberikan dan menghapus tag soket individual secara manual menggunakan TrafficStats.tagSocket() dan TrafficStats.untagSocket(). Contoh:

Kotlin

    TrafficStats.setThreadStatsTag(0xF00D)
    TrafficStats.tagSocket(outputSocket)
    // Transfer data using socket
    TrafficStats.untagSocket(outputSocket)
    

Java

    TrafficStats.setThreadStatsTag(0xF00D);
    TrafficStats.tagSocket(outputSocket);
    // Transfer data using socket
    TrafficStats.untagSocket(outputSocket);
    

Library HttpURLConnection menambahkan tag ke soket secara otomatis berdasarkan nilai TrafficStats.getThreadStatsTag() saat ini. Library ini juga menambahkan dan menghapus tag dari soket saat didaur ulang melalui kumpulan keep-alive.

Kotlin

    private class IdentifyTransferSpikeTask : AsyncTask<String, Nothing, String>() {

        override fun onPreExecute() = TrafficStats.setThreadStatsTag(0xF00D)

        override fun doInBackground(vararg urls: String): String {
            try {
                // Make network request using HttpURLConnection.connect()
            }
        }

        override fun onPostExecute(result: String) = TrafficStats.clearThreadStatsTag()
    }
    

Java

    private class IdentifyTransferSpikeTask extends AsyncTask<String, Void, String> {
        @Override
        protected void onPreExecute() {
          TrafficStats.setThreadStatsTag(0xF00D);
        }

        @Override
        protected String doInBackground(String... urls) {
            try {
                // Make network request using HttpURLConnection.connect()
            }
        }

        @Override
        protected void onPostExecute(String result) {
            TrafficStats.clearThreadStatsTag();
       }
    }
    

Pemberian tag soket didukung pada Android 4.0, tetapi statistik real time hanya akan ditampilkan pada perangkat yang menjalankan Android 4.0.3 atau yang lebih tinggi.