HeadlinesBriefing favicon HeadlinesBriefing.com

Performa Thread Utama Browser

Hacker News •
×

Apa yang terlintas di pikiran saat Anda mendengar "optimasi frontend"? Bagi kebanyakan kami, itu hal-hal seperti mengurangi permintaan jaringan, memperkecil bundle, atau memanfaatkan cache dengan baik. Di luar itu, mungkin mengurangi re-render atau menyesuaikan kapan resource dimuat. Thread utama biasanya tidak jadi pembicaraan, dan ada alasannya: di kebanyakan layar ia tidak pernah jadi masalah.

Tapi di layar dengan banyak interaksi, di mana data mengalir langsung dan scroll, animasi, dan input saling terjalin, gambarannya berubah. Berapa pun yang Anda hemat di jaringan dan ukuran bundle, layar beku saat thread utama diblokir. Anda pasti pernah nemu situs di mana scroll sesekali nge-lag, tombol respons agak lambat, atau huruf yang diketik di kotak pencarian muncul setengah beat ketinggalan.

Itu nggak cukup parah buat bikin kesal, tapi mengganggu secara halus. Jenis jank seperti itulah tampilan thread utama yang diblokir. Saat kita developer nemu jank kayak gini, reaksi biasa adalah nanya "apakah kode saya lambat?" dan mulai bedah algoritma atau cari komputasi yang sia-sia.

Tapi di kebanyakan kasus, kecepatan kode bukan masalahnya. Kode nggak lambat. Dia cuma kebetulan jadi kode yang nahan thread utama.

Browser punya beberapa thread, tapi hampir semua yang bisa kita sentuh dari kode terkonsentrasi di thread utama. Komputasi, rendering, penanganan event, penanganan respons jaringan, dan internal framework Anda semuanya diproses di sana. Satu resource, gunungan pekerjaan.

Thread utama browser mahal. Kebanyakan waktu nggak bikin repot, tapi begitu Anda coba lakukan sesuatu yang ambisius, ngurusin thread utama jadi bagian penting. Artikel ini soal cara ngurusin resource mahal itu.

Yuk mulai dari apa yang sebenarnya dilakukan thread utama. Pekerjaannya terbagi dua kategori besar. Pertama adalah menjalankan JavaScript.

Kode yang kita tulis, beserta event handler, timer, callback respons jaringan, dan internal framework, semuanya jalan di sini. Task-task ini dieksekusi sesuai urutan masuk antrian, kapan ada gap, tanpa hubungin sama siklus refresh layar. Kedua adalah menggambar layar.

Kalau DOM atau style berubah dan layar butuh update, browser lewat kira-kira langkah ini, berurutan, buat produce satu frame. Jalankan callback requestAnimationFrame — JavaScript terdaftar jalan tepat sebelum frame digambar Perhitungan style — hitung nilai CSS final tiap elemen Layout — hitung posisi dan ukuran tiap elemen (disebut juga reflow) Paint — generate perintah paint yang njelasin mau gambar apa di warna apa Kalau nggak ada yang berubah, langkah-langkah ini diskip total, jadi mereka nggak harus jalan tiap frame. Hanya langkah compositing final, yang ambil output yang di-produce dan rakit di layar, yang dilewatin ke compositor thread.

Dengan kata lain, sebagian besar front-half pipeline yang gambar layar itu tanggung jawab thread utama. Pipeline rendering untuk update layar Biar layar kelihatan smooth, frame harus digambar di refresh rate display. Di display 60Hz paling umum, berarti 60 frame per detik, atau kira-kira 16,6 milidetik per frame.

Dan Anda nggak bisa pake semuanya. Setelah dikurangi biaya proses sendiri browser, budget praktis biasanya dianggap kira-kira 10 milidetik, dan di device 120Hz budget-nya sendiri dipotong setengah. Masalahnya adalah dua jenis kerja di atas berdiri dalam satu baris di thread yang sama.

JavaScript didesain sekitar model event loop single-threaded. Thread utama proses satu task pada satu waktu, dan selama task itu jalan, nggak ada apa-apa yang bisa terjadi. Kalau satu fungsi JavaScript jalan 200 milidetik, maka selama 200 milidetik browser nggak bisa repaint layar atau terima klik dari user.

Lawan budget frame kira-kira 10 milidetik, itu jumlah waktu yang fatal. Task yang ru...