Meningkatkan performa aksesibilitas Chromium

Postingan ini berasal dari kontributor Chromium, Ahmed Elwasefi, yang membagikan kisahnya menjadi kontributor melalui Google Summer of Code, dan masalah performa aksesibilitas yang telah ia identifikasi dan perbaiki.

Saat mendekati tahun terakhir di jurusan teknik komputer di German University di Kairo, saya memutuskan untuk mencari peluang untuk berkontribusi pada open source. Saya mulai menjelajahi daftar masalah Chromium yang mudah bagi pemula dan merasa terutama tertarik dengan aksesibilitas. Pencarian saya untuk mendapatkan panduan mengarahkan saya kepada Aaron Leventhal, yang keahlian dan kesediaannya untuk membantu menginspirasi saya untuk bekerja sama dengannya dalam sebuah project. Kolaborasi ini menjadi pengalaman Google Summer of Code saya, tempat saya diterima untuk bekerja dengan Tim Aksesibilitas Chromium.

Setelah berhasil menyelesaikan Google Summer of Code, saya terus mengatasi masalah scroll yang belum terselesaikan, yang didorong oleh keinginan untuk meningkatkan performa. Berkat dua hibah dari program OpenCollective Google, saya dapat terus mengerjakan project ini sekaligus melakukan tugas tambahan yang berfokus pada penyederhanaan kode untuk performa yang lebih baik.

Postingan blog ini membagikan perjalanan saya dengan Chromium selama satu setengah tahun terakhir, yang menjelaskan peningkatan teknis yang telah kami lakukan, terutama di area performa.

Pengaruh kode aksesibilitas terhadap performa di Chrome

Kode aksesibilitas Chrome membantu teknologi pendukung seperti pembaca layar mengakses web. Namun, jika diaktifkan, fitur ini dapat memengaruhi waktu pemuatan, performa, dan masa pakai baterai. Oleh karena itu, jika tidak diperlukan, kode ini tetap tidak aktif untuk menghindari perlambatan performa. Sekitar 5-10% pengguna mengaktifkan kode aksesibilitas, sering kali karena alat seperti pengelola sandi dan software antivirus yang menggunakan API aksesibilitas platform. Alat ini mengandalkan API ini untuk berinteraksi dengan dan mengubah konten halaman, seperti menemukan kolom sandi untuk pengelola sandi dan pengisi formulir.

Total degradasi dalam metrik inti belum diketahui, tetapi eksperimen terbaru yang disebut Penonaktifan Aksesibilitas Otomatis (menonaktifkan aksesibilitas saat tidak digunakan), menunjukkan bahwa degradasi tersebut cukup tinggi. Masalah ini terjadi karena banyaknya komputasi dan komunikasi di dua area utama codebase aksesibilitas Chrome: perender dan browser. Perender mengumpulkan informasi tentang konten web dan perubahan pada konten, menghitung properti aksesibilitas untuk hierarki node. Setiap node kotor kemudian diserialisasi dan dikirim melalui pipe ke thread UI utama proses browser. Thread ini menerima dan mendeserialisasi informasi ini ke dalam hierarki node yang identik, lalu akhirnya mengonversinya ke bentuk yang sesuai untuk teknologi pendukung pihak ketiga seperti pembaca layar.

Peningkatan pada aksesibilitas Chromium

Project berikut diselesaikan selama Summer of Code, lalu setelahnya, didanai oleh program Google OpenCollective.

Peningkatan cache

Di Chrome, ada struktur data khusus yang disebut hierarki aksesibilitas yang mencerminkan hierarki DOM. Ini digunakan untuk membantu teknologi pendukung mengakses konten web. Terkadang, saat perangkat memerlukan informasi dari hierarki ini, perangkat mungkin belum siap, sehingga browser harus menjadwalkan permintaan tersebut untuk nanti.

Sebelumnya, penjadwalan ini ditangani menggunakan metode yang disebut penutupan, yang melibatkan penempatan callback ke dalam antrean. Pendekatan ini menambahkan pekerjaan tambahan karena cara penutupan diproses.

Untuk meningkatkannya, kami beralih ke sistem yang menggunakan enum. Setiap tugas diberi nilai enum tertentu, dan setelah hierarki aksesibilitas siap, metode yang benar untuk tugas tersebut akan dipanggil. Perubahan ini membuat kode lebih mudah dipahami dan meningkatkan performa lebih dari 20%.

Grafik pengujian performa runtime.
Grafik runtime beberapa pengujian performa yang menunjukkan penurunan yang terlihat sekitar 20% di semua pengujian.

Menemukan dan memperbaiki masalah performa scroll

Selanjutnya, saya mempelajari peningkatan performa saat kita menonaktifkan serialisasi kotak pembatas. Kotak pembatas adalah posisi dan ukuran elemen di halaman web, termasuk detail seperti lebar, tinggi, dan posisinya relatif terhadap elemen induknya.

Untuk mengujinya, kami menghapus kode yang menangani kotak pembatas untuk sementara dan menjalankan pengujian performa untuk melihat dampaknya. Satu pengujian, focus-links.html, menunjukkan peningkatan besar sekitar 1.618%. Penemuan ini menjadi dasar untuk pekerjaan lebih lanjut.

Menyelidiki pengujian lambat

Saya mulai menyelidiki mengapa pengujian tertentu tersebut lambat dengan bounding box. Semua yang dilakukan pengujian adalah menempatkan fokus pada beberapa link satu per satu. Oleh karena itu, masalah utamanya harus berfokus pada elemen atau scroll yang terjadi dengan tindakan fokus. Untuk mengujinya, saya menambahkan {preventScroll: true} ke panggilan focus() dalam pengujian performa, yang menghentikan scroll.

Dengan menonaktifkan scroll, waktu pengujian turun menjadi 1,2 milidetik saat penghitungan kotak pembatas aktif. Hal ini menunjukkan bahwa scroll adalah masalah yang sebenarnya.

Hasil pengujian dengan scroll dinonaktifkan.
Runtime pengujian link fokus turun dari 20 md menjadi 1,1 md saat scroll dinonaktifkan atau serialisasi kotak pembatas dihapus.

Saya membuat pengujian baru bernama scroll-in-page.html untuk mereplikasi pengujian focus-links, tetapi bukan menggunakan fokus, pengujian ini men-scroll elemen dengan scrollIntoView(). Saya menguji scroll yang lancar dan instan, dengan dan tanpa penghitungan kotak pembatas.

Hasil pengujian untuk pengujian baru.
Waktu yang diperlukan untuk memproses scroll dalam scroll instan adalah 65 mdtk, sedangkan scroll halus memerlukan waktu 123 mdtk.

Hasilnya menunjukkan bahwa dengan scrolling instan dan kotak pembatas, proses ini memerlukan waktu sekitar 66 md. Scroll yang lancar bahkan lebih lambat, sekitar 124 md. Saat kita menonaktifkan kotak pembatas, tidak perlu waktu lama karena tidak ada peristiwa yang dipicu.

Kita tahu kasusnya, tetapi mengapa hal itu terjadi?

Sekarang kita telah mempelajari bahwa scroll adalah sumber banyak kelambatan dalam serialisasi aksesibilitas, tetapi kita masih harus mencari tahu alasannya. Untuk menganalisis hal ini, Dua alat yang disebut perf dan pprof digunakan untuk menguraikan pekerjaan yang dilakukan dalam proses browser. Alat ini sering digunakan di C++ untuk pembuatan profil. Grafik berikut menunjukkan cuplikan bagian yang menarik.

Grafik pengujian scroll yang diprofilkan.
Grafik yang dihasilkan dari pembuatan profil pengujian scroll. Menunjukkan bahwa waktu sebagian besar dihabiskan dalam panggilan ke fungsi yang disebut Unserialize serta fungsi lain yang disebut IsChildOfLeaf.

Setelah menyelidiki, kami mendapati bahwa masalahnya bukan kode deserialisasi itu sendiri, tetapi frekuensi panggilan ke kode tersebut. Untuk memahami hal ini, kita perlu melihat cara kerja update aksesibilitas di Chromium. Update tidak dikirim satu per satu; sebagai gantinya, ada lokasi pusat yang disebut AXObjectCache yang menyimpan semua properti. Saat node berubah, berbagai metode akan memberi tahu cache untuk menandai node tersebut sebagai kotor untuk serialisasi di lain waktu. Kemudian, semua properti catatan kotor, termasuk properti yang tidak berubah, akan diserialisasi dan dikirim ke browser. Meskipun desain ini menyederhanakan kode dan mengurangi kompleksitas dengan memiliki satu jalur update, desain ini menjadi lambat saat ada peristiwa "tandai sebagai kotor" yang cepat, seperti dari scroll. Satu-satunya hal yang berubah adalah nilai scrollX dan scrollY; tetapi, kita melakukan serialisasi properti lainnya dengan nilai tersebut setiap saat. Kecepatan update di sini mencapai lebih dari dua puluh kali per detik.

Serialisasi kotak pembatas mengatasi masalah ini dengan menggunakan jalur serialisasi yang lebih cepat yang hanya mengirim detail kotak pembatas, sehingga memungkinkan update cepat tanpa memengaruhi properti lainnya. Metode ini menangani perubahan kotak pembatas secara efisien.

Perbaikan scroll

Solusinya jelas: sertakan offset scroll saat ini dengan serialisasi kotak pembatas. Hal ini memastikan bahwa update scroll diproses melalui jalur cepat, sehingga meningkatkan performa tanpa penundaan yang tidak perlu. Dengan memaketkan offset scroll dengan data kotak pembatas, kami mengoptimalkan proses untuk update yang lebih lancar dan lebih efisien, sehingga menciptakan pengalaman yang lebih lancar bagi pengguna dengan aksesibilitas yang diaktifkan. Peningkatan setelah penerapan perbaikan ini adalah hingga 825% dalam pengujian scroll.

Penyederhanaan kode

Dalam periode ini, saya berfokus pada kualitas kode sebagai bagian dari project yang disebut Onion Soup, yang menyederhanakan kode dengan mengurangi atau menghapus kode yang tidak perlu tersebar di seluruh lapisan.

Project pertama bertujuan untuk menyederhanakan cara data aksesibilitas diserialisasi dari perender ke browser. Sebelumnya, data harus melewati lapisan tambahan sebelum mencapai tujuannya, yang menambah kompleksitas yang tidak perlu. Kami menyederhanakan proses ini dengan mengizinkan data dikirim langsung, sehingga tidak perlu perantara.

Selain itu, kami mengidentifikasi dan menghapus beberapa peristiwa yang sudah tidak berlaku yang menyebabkan pekerjaan yang tidak perlu dalam sistem, seperti peristiwa yang dipicu saat tata letak selesai. Kami menggantinya dengan solusi yang lebih efisien.

Ada juga peningkatan kecil lainnya yang dilakukan. Sayangnya, peningkatan performa tidak dicatat untuk hal ini, tetapi dengan bangga kami sampaikan bahwa kode jauh lebih jelas dan dapat mendokumentasikan dirinya sendiri daripada sebelumnya. Hal ini sangat membantu untuk membuka jalan untuk peningkatan performa di masa mendatang. Anda dapat memeriksa perubahan yang sebenarnya di profil gerrit saya.

Kesimpulan

Bekerja dengan Tim Aksesibilitas Chromium adalah perjalanan yang memuaskan. Dengan mengatasi berbagai tantangan, mulai dari mengoptimalkan performa scroll hingga menyederhanakan codebase, saya telah mendapatkan pemahaman yang lebih mendalam tentang pengembangan dalam project skala besar seperti itu serta mempelajari alat penting untuk pembuatan profil. Selain itu, saya telah mempelajari betapa pentingnya aksesibilitas untuk membuat web yang inklusif bagi semua orang. Peningkatan yang kami lakukan tidak hanya meningkatkan pengalaman pengguna bagi mereka yang mengandalkan teknologi pendukung, tetapi juga berkontribusi pada performa dan efisiensi browser secara keseluruhan.

Hasil performanya sangat mengesankan. Misalnya, beralih ke penggunaan enum untuk menjadwalkan tugas meningkatkan performa sebesar lebih dari 20%. Selain itu, perbaikan scroll kami menghasilkan pengurangan pengujian scroll hingga 825%. Perubahan penyederhanaan kode tidak hanya membuat kode lebih jelas dan lebih mudah dikelola, tetapi juga membuka jalan untuk peningkatan di masa mendatang.

Saya ingin mengucapkan terima kasih kepada Stefan Zager, Chris Harrelson, dan Mason Freed atas dukungan dan bimbingan mereka sepanjang tahun, dan terutama kepada Aaron Leventhal, yang tanpanya peluang ini tidak akan mungkin terjadi. Saya juga ingin mengucapkan terima kasih kepada Tab Atkins-Bittner dan tim GSoC atas dukungan mereka.

Bagi mereka yang ingin berkontribusi pada project yang bermakna dan mengembangkan keterampilan mereka, saya sangat merekomendasikan untuk terlibat dengan Chromium. Ini adalah cara yang bagus untuk belajar, dan program seperti Google Summer of Code menawarkan titik awal yang sangat baik untuk perjalanan Anda.