Bagaimana cara menyimpan sumber daya di browser dan tidak merusak web. Laporan Yandex

Terlepas dari pertumbuhan kinerja perangkat, web menjadi semakin menuntut pada memori dan prosesor. Render yang tepat dan alokasi sumber daya yang cerdas di seluruh tab merupakan bagian penting untuk menyelesaikan masalah ini. Konstantin Kramlih PurplePowder mengabdikan pidatonya di konferensi "I Frontend" untuk algoritma yang meningkatkan produktivitas dan menghemat sumber daya baik dalam proyek Chromium dan di Yandex.Browser.

Beberapa di antaranya - misalnya, teknologi Hibernate - kami telah disortir dalam pos terpisah . Laporan tulang mencakup masalah secara lebih luas: tidak hanya dari sudut pandang beralih tab, tetapi juga memperhitungkan metode rendering konten, ubin dan lapisan halaman.

Menjelang akhir, pengembang antarmuka web dapat mempelajari cara mengidentifikasi dan menyelesaikan masalah kinerja situs web.


- Nama saya Kostya, saya adalah kepala grup pengembangan komponen internal di tim Yandex.Browser. Di Browser, saya telah melakukan hal-hal yang berbeda selama kurang lebih lima tahun: dari semua decoding di browser, dari semua video HTML5, hingga rendering, rendering, dan proses serupa lainnya.

Selama satu setengah hingga dua tahun terakhir, saya telah terlibat dalam proyek yang berkaitan dengan penghematan sumber daya di browser: CPU, memori, baterai.

Anda mengatakan - Kostya, di halaman pada tahun 2019, di mana masalah dengan sumber daya? Anda dapat membeli perangkat apa pun yang Anda inginkan dengan sumber daya apa pun. Tetapi jika kita beralih ke statistik Mozilla terbuka, kita akan melihat bahwa setengah dari pengguna memiliki memori 4 GB atau kurang. Dan banyak pengguna yang memiliki satu atau dua core fisik, mereka membuat proporsi yang cukup besar dari audiens Anda. Di dunia ini kita hidup.



Berapa banyak dari Anda yang sering melihat tab ini? Inilah yang terjadi dalam kasus pengguna biasa yang memiliki sedikit RAM dan komputer lama.



Apa yang harus dilakukan Masalahnya bukan rahasia bagi siapa pun, mereka mulai aktif bertarung dengannya sekitar tiga tahun lalu. Sejak itu, kacang secara bertahap dikencangkan dengan berbagai cara. Mari saya tunjukkan sebuah contoh yang berkeliling Stack Overflow sekitar 2016. Berikut ini cuplikan sederhana. Hal ini hanya memperbarui judul dan menetapkan waktu yang telah berlalu sejak peluncuran terakhir fungsi ini. Apa yang harus diperoleh secara ideal? Setiap 100 ms dalam judul harus ditulis + -100. Beruntung sekali.



Tetapi bagaimana jika kita membuka dan melakukan ini? Adakah yang mengalami hal ini? Pertanyaannya adalah Stack Overflow: apa yang tidak bisa dikerjakan Cookie Clicker di tab latar belakang saya? Ini adalah salah satu inisiatif Chromium pertama yang bertujuan mengurangi penggunaan CPU di browser. Idenya adalah jika pengguna tidak menggunakan tab sekarang, maka dia tidak membutuhkannya sekarang - mari kita beri JS padanya.

Peramban mencoba mempertahankan beban CPU pada tab ini sekitar 1% - mulai menjeda semua jenis penghitung waktu, eksekusi JS, dll. Ini adalah salah satu langkah pertama di masa depan yang cerah.



Setelah beberapa waktu di browser, Anda akan mendapatkan situasi bahwa tab latar belakang berhenti berfungsi sama sekali. Inilah masa depan yang cerah yang saya bicarakan. Menurut rencana Chromium, yang mereka nyuarakan di BlinkOn terakhir, pada tahun 2020 mereka berencana untuk melakukannya: biarkan tab memuat dan jika latar belakang, itu tidak akan melakukan apa-apa. Anda selalu harus siap untuk ini.



Di Yandex.Browser, kami juga menangani masalah seperti itu, tetapi menyelesaikannya dengan kurang kategoris dan tidak merusak seluruh web. Kami menciptakan mode hemat energi yang mematikan decoding pada prosesor dan hanya menyisakan decoding pada kartu video, dan juga menurunkan FPS dan menonaktifkan beberapa animasi yang tidak diperlukan saat ini dan sebagai gantinya pengguna harus menghemat baterai. Ini memberi kami sekitar satu jam masa pakai baterai ekstra. Siapa pun dapat memeriksa, misalnya, diperiksa .



Saya pikir beberapa orang akan mengatakan: Kostya, Anda "merusak" web, membantu beberapa pengguna, tetapi tidak membuat sesuatu yang lebih pintar. Tambahkan hardcore! Bagaimana cara browser menggambar halaman?



Singkatnya, konsep lapisan adalah ketika browser mencoba memecah halaman menjadi lapisan dan menggambarnya secara terpisah. Ini dilakukan agar beberapa animasi dilakukan dan tidak memaksa untuk menggambar ulang apa yang statis. Browser melakukan ini pada heuristik yang berbeda. Misalnya - mencoba untuk memilih elemen video ke dalam lapisan terpisah, yang, jelas, cepat dan sering digambar ulang. Dan jika itu ditampilkan di suatu tempat, maka Anda tidak perlu menggambar kembali semuanya di bawahnya.

Selain itu, setiap lapisan dibagi menjadi ubin seperti itu - 256 x 256 persegi panjang. Di inspektur Anda dapat melihat sesuatu seperti ini. Ada bingkai yang dibagi menjadi banyak ubin.





Apa itu dan mengapa itu dibutuhkan? Pertama-tama, untuk memprioritaskan rendering. Jika kita memiliki sosis besar, yang kita semua gambar, lalu mengapa kita perlu menggambar semua ini jika sekarang pengguna hanya melihat apa yang dia miliki di ViewPort?



Menggunakan pendekatan ini, pertama-tama kita menggambar hanya apa yang dilihat pengguna saat ini di ViewPort, lalu satu ubin di sekitar, lalu ke arah gulir. Jika pengguna gulir ke bawah - tarik ke bawah, jika ke atas. Semua yang lain akan ditarik hanya jika kita memiliki kuota untuk ubin ini dan kita dapat menggambarnya, setelah itu pengguna akan melihatnya. Atau mungkin tidak pernah.



Ini juga banyak membantu penyandang cacat. Misalkan pengguna membuka halaman, memilih bagian, dan kami tidak perlu menggambar semuanya. Kami dapat meninggalkan sebagian besar rendering sebelumnya. Kami akan menggambar ulang enam ubin di sini, dan semuanya akan baik-baik saja.



Tepat pada level ini, beberapa optimasi sangat berhasil dibuat. Misalnya, Chromium membuat pengoptimalan sekitar tahun 2017.



Jika kami hanya memiliki rendering kecil, kami hanya melakukannya. Lalu kursor berkedip, dan kami menggambar ulang hanya area kursor, tetapi tidak seluruh area ubin ini. Kami sangat menghemat CPU agar tidak menggambar ulang semuanya.



Ini juga membantu menghemat memori. Apa masalahnya di sini? Seluruh persegi panjang putih. Bayangkan itu akan menjadi tekstur 256 oleh 256, empat byte per piksel. Meskipun tampaknya area ini dapat dikodekan hanya dengan lima angka: koordinat, lebar, tinggi dan warna.



Di Chromium, optimalisasi area monokrom telah dilakukan. Jika browser memahami bahwa tidak ada render dalam persegi panjang ini, bahwa itu sepenuhnya monokrom, tidak transparan dan memenuhi beberapa persyaratan lain, maka kami hanya memberi tahu kartu video - gambar persegi panjang putih, jangan pilih seluruh tekstur.

Apa lagi yang bisa dioptimalkan di sini? Jika Anda melihat ubin yang tersisa - mereka memiliki sedikit konten dan area besar warna putih. Di Yandex.Browser, kami memikirkan hal ini dan membuat mekanisme yang kami sebut ubin adaptif.



Ada satu kotak kecil, ubin. Ada sedikit konten di tengah ubin. Kami memilihnya dan - hanya di bawahnya - tekstur. Segala sesuatu yang lain juga dibagi menjadi beberapa area, yang kita bicarakan kartu video: hanya menggambar putih di sini ukuran ini.



Halaman ini juga mulai menyimpan semua yang disorot dengan warna merah. Pada halaman yang lebih kompleks, tampilannya seperti ini.



Penting untuk dipahami bahwa masih ada banyak lapisan dan setiap lapisan digambar seperti ini. Di setiap lapisan, Anda dapat menghemat sejumlah memori. Pendekatan ini memungkinkan kami untuk menghemat sekitar 40% dari memori video rata-rata untuk semua pengguna.

Lebih hardcore! Mereka menyimpan sedikit memori di sini, mereka “menghancurkan” web - mengapa tidak “menghancurkan” web lebih lanjut?

Di Chromium ada sesuatu seperti kebijakan: jika pengguna tidak menggunakan tab latar belakang, jika ia meninggalkannya, maka ia tidak membutuhkannya. Jika kita sekarang tidak memiliki memori dan browser sekarang sedang berbaring, maka mari kita ambil tab tertua yang sudah lama tidak digunakan pengguna dan bunuh. Dia akan tetap berada di antarmuka, tetapi prosesnya tidak lagi ada, semua JS akan mati. Apakah boleh atau tidak? Sungguh aneh mengajukan pertanyaan semacam itu di pesta front-end dan mengharapkan jawaban selain "Apa yang kamu lakukan?"



Maka itu tidak banyak. Berikut adalah komentar nyata dari blog Chromium: Anda merusak semua aplikasi saya untuk saya, ada semacam permainan - dan lompat, tidak memiliki status apa-apa. Penting untuk dipahami bahwa tidak ada handler yang tidak bekerja, seolah-olah kita hanya mengeluarkan tab ini. Pengguna kemudian kembali ke sana, dan kami memuatnya kembali dari jaringan, seolah-olah tidak ada yang terjadi.

Kemudian pendekatan ini ditinggalkan sementara dan muncul dengan ide serius yang lebih serius. Mereka memanggilnya membuang.



Apa gunanya Ini adalah pembunuhan tab yang sama, hanya dikendalikan. Itu disebut kata pintar Page Lifecycle API . Jika Anda memiliki tab, dan pengguna belum melihatnya untuk waktu yang lama, itu dapat masuk ke status beku. Browser mengatakan melalui acara: Saya akan membekukanmu sekarang. Setelah memproses acara, tidak ada yang dilakukan sama sekali. Lakukan apa yang Anda butuhkan, bersiap-siaplah.

Kemudian dapat keluar dari keadaan beku melalui acara resume, seharusnya tidak terjadi apa-apa. Atau, jika peramban benar-benar perlu mengosongkan memori sekarang, itu hanya membutuhkan dan membunuhnya. Tetapi jika pengguna kembali ke tab ini, kami akan memuatnya kembali dan mengatur bidang yang dibuang untuk dokumen.



Saat ini Anda sudah dapat berlangganan ke acara ini dan menangkapnya, entah bagaimana prosesnya. Jika tab benar-benar mati, Anda dapat memeriksa bidang yang dibuang. Ini berarti Anda telah dipulihkan setelah dibuang. Anda dapat memulihkan keadaan sebelumnya.



Kami di Yandex.Browser berpikir beberapa tahun yang lalu: mengapa tidak menggunakan pendekatan kardinal yang kompleks. Mereka memanggilnya Hibernate.



Apa gunanya Ada beberapa tab, beberapa jenis JS berjalan, semacam negara. Proses terpisah dibuat untuk setiap tab: di sini video dapat diputar, di sini Anda meninggalkan sesuatu dalam formulir. Hibernate tiba - dan tidak ada proses. Kita semua mendapatkannya. Tetapi jika sekarang kita beralih kembali ke tab ini, proses akan kembali dan seluruh negara akan berada di tempatnya, video akan terus diputar dari saat yang tepat, semua teks di bidang akan tetap di tempatnya.



Apa yang telah kita lakukan Tiga hal paling penting hidup di dalam masing-masing renderer: V8, yang menjalankan seluruh JS, Blink, yang menyimpan seluruh DOM, dan beberapa jenis penjilidan browser, yang membantu menghubungkan semuanya bersama-sama, dengan tab dan yang lainnya.



Misalnya, pertimbangkan sampel. Di sini kita menunggu onload terjadi, dan menambahkan elemen div baru ke pohon DOM. Untuk browser, tampilannya seperti ini.



Tentu saja, ada pohon DOM, ia memiliki beberapa bidang, objek terkait, dan ada entitas seperti itu.



Dalam V8, keadaan setiap node disimpan, dan node ini dikaitkan dengan objek blink melalui lapisan pengikat. Apa yang telah kita lakukan Kami mengambil serializer dari V8, membuat serial seluruh negara V8, menemukan semua objek terkait di Blink, menulis plus serialisator yang menyimpan seluruh pohon DOM, membuat serial, lalu menulis ke disk, dikompresi, dan dienkripsi. Dan kami mengajarkan browser untuk memulihkan dari snapshot seperti itu kembali. Artinya, ketika pengguna pergi ke tab seperti itu, kami memperluasnya, mendekripsi dan menunjukkannya kepada pengguna, mengembalikannya sepenuhnya. ( Posting terpisah tentang Hibernate - perkiraan.)

Saat ini, Hibernate diterbitkan untuk semua orang di stabil dan memungkinkan setiap pengguna untuk menyimpan rata-rata satu atau dua tab. Artinya, ia memiliki rata-rata satu tab yang selalu disimpan, atau mungkin dua. Ini menghemat memori untuk pengguna yang memiliki lebih dari 10 tab - seperti yang kami lakukan dengan Anda, tetapi kami tidak representatif.

Saya memberi tahu bagaimana browser berusaha membantu, tetapi sekarang Anda masing-masing dapat melakukan sesuatu untuk mempercepat situs, meningkatkan kinerjanya. Anda bisa datang dan lakukan hari ini juga.

Pertama, Anda perlu memahami jika ada masalah memori.



Ada gejala-gejala tertentu: situs mulai menurun, atau memudar muncul. Biasanya ini berarti bahwa pemulung dipicu, seluruh dunia beku dan tidak ada yang ditarik. Atau situs itu hanya terus-menerus melambat - hal itu juga terjadi.

Anda perlu memahami jika ada masalah. Kami melihat apa yang terjadi dengan memori JS.



Jika ia melompat bolak-balik atau tumbuh terus menerus, ini bukan gejala yang baik. Atau tumbuh terus menerus.



Dalam hal ini, Anda selalu dapat mengambil snapshot melalui DevTools. Adakah yang peduli dengan kebocoran di JS? Jika seseorang tidak tahu, di JS sangat mungkin untuk membuat kebocoran.



Misalnya, Anda memiliki variabel global tempat Anda menambahkan node yang tidak dimasukkan ke dalam pohon. Anda lupa tentang mereka, dan ternyata mereka memakan ratusan kilobyte, atau bahkan megabyte.



Sebenarnya, tidak jelas apa yang harus dilakukan dengan node yang terpisah tersebut. Anda dapat menariknya keluar dari pohon, dan kemudian memasukkannya kembali. Karena biasanya keadaan gambar atau sesuatu yang lain tetap bersama mereka. Dengan demikian, Anda dapat menemukannya dan mengatasi masalahnya.



Anda juga dapat melihat alokasi memori pada timeline. Jika Anda memiliki pembuangan sistematis dan tidak pernah membersihkan, ini juga pertanda buruk, saya pikir semua orang mengerti ini.



Dan Anda bisa bermain dengan layer pada tab Anda. Browser umumnya bekerja dengan heuristik dalam hal ini - ia mencoba untuk memisahkan objek yang dianggapnya sering berubah menjadi lapisan yang terpisah. Tetapi kadang-kadang itu tidak bekerja dengan baik, dan ternyata Anda memiliki banyak lapisan yang menghabiskan banyak memori. Anda selalu dapat melihat apakah Anda memiliki situasi seperti itu, menghilangkan beberapa lapisan dan mencari tahu berapa banyak memori yang ditempati lapisan ini.



Lapisan masalah lainnya adalah kinerja. setTimeout adalah ide buruk untuk animasi. Ini tidak berfungsi seperti yang diinginkan browser untuk merender halaman. Ini mungkin tidak berfungsi dalam fase: browser meminta bingkai, tetapi belum ada animasi, karena setTimeout tidak berfungsi. Atau itu dapat bekerja bahkan ketika Anda tidak perlu menggambar apa pun. Pengguna telah pergi, masih ada beberapa pekerjaan latar belakang yang tersisa, tetapi kami akan bekerja dengannya melalui setTimeout.

Ini adalah pendekatan yang benar yang akan dipanggil kembali hanya oleh Anda ketika browser perlu menggambar halaman ini.



Saya juga ingin mengingatkan Anda bahwa jika browser ingin menggambar 60 frame per detik, itu berarti bahwa untuk setiap frame dibutuhkan sekitar 16 ms.



Dan jika Anda menempati arus utama lebih dari 16 ms, maka Anda memiliki bingkai lompatan dijamin, yang agak tidak menyenangkan bagi pengguna: situs mulai menyentak. Oleh karena itu, semua kerja keras dengan benar dimasukkan ke utas latar belakang, yang Anda hanya mengembalikan hasilnya.



Atau pendekatan lain adalah menggunakan microtasking. Buat antrian tugas, proses setelah beberapa waktu, sampai kuota selesai, dan biarkan browser menggambar halaman dengan tenang.



Secara alami, Anda dapat menambahkan lapisan baru. Browser bekerja pada heuristik dan mencoba untuk memilih layer yang dianggap perlu. Tetapi jika Anda tahu bahwa saat ini elemen ini akan dianimasikan, lebih baik memberi tahu browser secara eksplisit bahwa Anda perlu memilih elemen ini di lapisan yang terpisah. Maka itu akan ditarik lebih efisien.



Pendekatan menarik terbaru - mengeluh. Jika Anda memiliki masalah, selalu bermanfaat untuk datang dan berbicara. Mungkin masalah ini dapat dengan mudah ditangani, dan kami akan saling membantu.

Sedikit latar belakang. Fitur ini sedang dikerjakan. Kami memiliki tim halaman pengembangan mesin pencari. Mereka memiliki metrik seperti saat memberikan cuplikan pertama. Jika pengguna sebelumnya melihat tautan pertama yang perlu Anda klik, dan yang kemungkinan besar memberinya jawaban yang benar, maka jauh lebih baik untuk menggambarnya secepat mungkin. Mereka datang dan bertanya apakah mungkin untuk mempercepat kali ini, karena mereka semua terjepit.

Kami menginvestigasi, melakukan uji coba, membuat prototipe, dan ternyata kami bisa melakukan ini jika situs memberi tahu kami apa yang harus digambar terlebih dahulu. Kami menguji dan melihat bahwa itu meningkatkan kinerja kami. Sekarang kami sedang menguji ini dalam produksi untuk audiens kecil. Kami melihat apa yang akan terjadi. Tetap disini.

Dunia tidak tinggal diam. Pengguna mulai menginginkan lebih dan lebih banyak lagi, browser berubah, web berubah. Ini normal. Kami mencoba tidak hanya membuat fitur makanan, tetapi juga untuk membantu pengguna dengan segala cara yang mungkin untuk mendapatkan pengalaman terbaik dalam hal konsumsi konten. Dan Anda selalu harus siap untuk perubahan di browser populer apa pun. Wajar jika ada masalah - ayo, kami siap berdiskusi dan saling membantu.

Di sini saya mengumpulkan berbagai tautan bermanfaat:

Source: https://habr.com/ru/post/id442456/


All Articles