Cara terbaik untuk bekerja dengan DOM

Ketika saya sedang menulis di Solid , saya memiliki kesempatan untuk memperkirakan jumlah upaya untuk mengoptimalkan kinerja pada grafik (benchmark).

DOM adalah pengembangan bottleneck front-end. Solusi yang berbeda dapat menghasilkan hasil yang serupa. Perpustakaan baru muncul setiap minggu, menggabungkan yang terbaik dari yang sebelumnya, untuk membuat kombinasi yang sempurna. Setelah beberapa waktu, mata saya mulai lari dari berbagai solusi.

Jangan salah paham terhadap saya. Saya suka melihat ide-ide baru menjadi hidup, tetapi mereka semua memiliki kekurangan, dan kadang-kadang menyebabkan hilangnya kenyamanan atau produktivitas. Saya memahami konsekuensi dari keputusan seperti itu, tetapi saya ingin membagikan pengamatan saya.

Apa cara tercepat untuk bekerja dengan DOM:

  • Dom virtual
  • Literal Templat Tagged
  • Dapat diamati dengan baik

Perbandingan


JS Frameworks Benchmark adalah proyek open source terbaik untuk membandingkan kinerja kerangka JavaScript UI. Lebih baik menjalankan tes secara lokal daripada menggunakan hasil resmi. Hasil dapat bervariasi menurut mesin. Karena saya menguji pada mesin yang lemah, kinerja akan terasa menurun.

Saya akan mengambil pendekatan terbaik dalam memberikan pohon DOM untuk menggambarkan redundansi solusi tertentu. Saya akan melakukan ini menggunakan kemampuan Solid untuk mendukung opsi render yang berbeda untuk mengenakan biaya ketika variabel berubah dan membandingkannya dengan hasil serupa dari kerangka kerja lain. Mari kita lihat mereka.

Varietas Padat:

  • solid - versi kerangka kerja dengan ES2015 proxy setter di atas fungsi pelacakan perubahan yang dibangun ke dalam templat simpul DOM kloning. Ini dicapai dengan mengkompilasi templat JSX (Kode)
  • sinyal padat - versi ini sama dengan yang sebelumnya, tetapi Sinyal mentah digunakan sebagai pengganti proxy. Ini mempersulit penggunaan perpustakaan, tetapi pada akhirnya kami mendapatkan bundel yang lebih kecil dan kinerja yang lebih baik (Kode)
  • solid-lit - versi ini tidak menggunakan precompilation JSX di runtime (Code)
  • solid-h - Versi ini menggunakan HyperScript untuk membuat `document.createElement` dengan cepat. Sisanya menggunakan implementasi yang sama dengan Solid (Code)

Perpustakaan lain:

  • domc β€” -, DOM DSL (domain specific language) HTML, index.html (Code)
  • surplus β€” JSX `document.createElement`. Solid (Code)
  • ivi β€” Inferno, DOM. HyperScript Helpers-esque (Code)
  • lit-html β€” , c . Tagged Template Literals DOM- (Code)
  • inferno adalah klon Bereaksi tercepat dan salah satu pustaka DOM Virtual tercepat. Menggunakan arahan JSX khusus untuk kinerja terbaik (Kode)

Beberapa kerangka kerja favorit Anda mungkin tidak ada di sini, tetapi daftar ini menampilkan versi yang dioptimalkan dari semua teknik yang akan Anda lihat dalam kerangka kerja paling populer. Anda dapat melihatnya sebagai indikator untuk mengevaluasi kapabilitas maksimum perpustakaan Anda. Jika Anda tertarik untuk membandingkan kinerja kerangka kerja populer, saya sarankan bagan ini.

Sebagai perbandingan, saya ingin menambahkan Majelis Web. Sayangnya, pada saat penulisan ini, catatan WASM adalah implementasi vanili tanpa abstraksi tingkat tinggi. (Kemudian mereka menambahkan wasm-bindgen ke framework - approx. Translator)

hasil


HyperScript (inferno, ivi, solid-h)


HyperScript menampilkan markup sebagai komposisi fungsi (seperti h atau React.createElement). Contohnya:

h('div', {id: 'my-element'}, [
  h('span', 'Hello'),
  h('span', 'John')
])

Kerangka kerja DOM virtual memiliki properti ini. Bahkan jika mereka menggunakan JSX atau mesin template DSL lainnya - di bawah tenda mereka masih dikonversi ke metode render elemen-demi-elemen. Ini digunakan untuk membangun pohon DOM virtual untuk setiap siklus render. Tetapi, seperti yang ditunjukkan di sini, fungsi yang diberikan dapat digunakan untuk membuat grafik dependensi reaktif, seperti dalam kasus Solid.



Seperti yang Anda lihat, perpustakaan dengan DOM virtual jauh lebih cepat. Solid kehilangan kinerja karena pembuatan grafik reaktif yang berlebihan. Perhatikan perbedaan dalam tolok ukur # 1, # 2, # 7, # 8, # 9.



Ingatannya kurang meyakinkan. Inferno dan versi Solid ini menunjukkan hasil yang hampir sama. Sementara ivi menggunakan lebih banyak memori.
, Solid, , VDOM. Solid , DOM, DOM. Solid JSX DOM . , . Solid fine grained evaluation . - .
β€”
Kerangka kerja pelacakan pembaruan yang reaktif menunjukkan hasil yang lebih baik saat memperbarui baris. Grafik ini akan menjelaskan popularitas VDOM dalam beberapa tahun terakhir. Cukuplah untuk mengatakan bahwa jika Anda menggunakan HyperScript dengan pembaruan ini, maka Anda lebih baik beralih ke Virtual DOM.

Templat string (domc, lit-html, solid-lit)


Setiap perpustakaan di sini memiliki kesamaan. Mereka diberikan berdasarkan templat elemen kloning, dijalankan dalam runtime dan tidak menggunakan VDOM. Tetapi mereka masih memiliki perbedaan. DomC dan lit-html menggunakan perbedaan top-down yang mirip dengan Virtual DOM, sedangkan Solid menggunakan grafik reaktif. Lit-html membagi templat menjadi beberapa bagian. DomC dan Solid mengkompilasi template ke jalur terpisah di runtime dan memperbaruinya.



Kategori ini memiliki rentang kinerja terluas. DomC adalah yang tercepat, dan lit-html adalah yang paling lambat. Lit Padat ada di tengah. DomC menunjukkan bahwa kesederhanaan kode mengarah pada kinerja terbaik.

DomC melorot hanya di bagian # 4 karena menghitung perbedaan node, yang menjadi lebih rumit dengan meningkatnya kedalaman. Ini cukup cepat, tetapi Anda perlu memvalidasi hasil pada data besar.

Solid Lit lebih produktif daripada Solid HyperScript. Kompilasi instan dalam runtime menghilangkan kelemahan membuat grafik reaktif, memungkinkan kerangka kerja untuk mengejar ketinggalan dengan ivi, pustaka VDOM tercepat (lihat tabel lengkap di akhir artikel).



DomC menunjukkan hasil yang baik dalam konsumsi memori. Ini terjadi karena kloning elemen template. Perlu dicatat bahwa pembuatan kode dalam runtime dapat memiliki overhead kinerja minimal dibandingkan dengan kompilasi pada tahap build. Mungkin ini adalah perbandingan yang tidak adil untuk lit-html karena kerangka kerjanya tidak menggunakan teknik ini. Namun wajar untuk mengatakan bahwa lit-html atau perpustakaan serupa seperti hyperHTML atau lighterHTML bukan cara terbaik untuk mengimplementasikan Tagged Template Literals. Dan Anda dapat mencapai hasil yang baik bahkan dalam runtime tanpa VDOM.

JSX yang dikompilasi sebelumnya (solid, solid-signal, surplus)


Pustaka ini menggunakan JSX, yang mengkompilasi menjadi DOM atau grafik reaktif pada tahap build. Template bisa apa saja, tetapi JSX menyediakan pohon sintaksis bersih yang meningkatkan pengalaman pengembang.



Kelompok ini memiliki hasil yang serupa, tetapi perbedaannya sangat penting. Ketiga menggunakan library yang sama untuk mengelola S.js negara . Menggunakan contoh Solid Signal, Anda dapat melihat bahwa fungsi pelacakan dengan kloning elemen template memberikan kinerja yang lebih besar. Implementasi standar Solid kelebihan beban menggunakan ES2015 Proxies, yang memperburuk hasil pada semua grafik. Surplus menggunakan `document.createElement`, yang menurunkan kinerja pada tes di mana baris # 1, # 2, # 7, # 8 dibuat.



Konsumsi memori memiliki hasil yang serupa. Dalam hal ini, proksi menambahkan lebih banyak kompleksitas daripada kloning elemen template.

Kesimpulannya di sini adalah bahwa proksi menurunkan kinerja dan lebih banyak perpustakaan harus mengkloning templat. Di sisi lain, Anda dapat mempertimbangkan kerugian kecil dalam kinerja karena proksi sebagai investasi. Contoh Solid memiliki jumlah kode terkecil di antara contoh lainnya - hanya 66 baris, memiliki 13% lebih sedikit non-spasi daripada Svelte - sebuah perpustakaan yang bangga dengan minimalisnya.

Terbaik di kelasnya (domc, ivi, solid-signal, vanillajs)


Sekarang mari kita ambil pemenang di setiap kategori dan membandingkannya dengan contoh brutal, efektif, tulisan tangan dalam vanilla JavaScript. Setiap implementasi mewakili salah satu solusi pelacakan keadaan populer. Anda bahkan dapat menggambar analogi antara perpustakaan ini dan Tiga Besar: Solid β†’ Vue, DomC β†’ Angular, ivi β†’ React. Anda akan mendapatkan hasil ini jika Anda menghapus semuanya berlebihan, kecuali untuk render, dan menyingkirkan kode 60-200kb.



DomC dan Solid sangat dekat dalam hal kinerja, ivi jauh di belakang, tetapi DomC, secara keseluruhan, lebih cepat. Kompleksitasnya dibandingkan dengan vanillaJS terasa kurang, tetapi kurang efektif dengan pembaruan parsial. Hanya kriteria ini yang bukan indikasi. Siapa pun yang berpikir bahwa VDOM lambat atau memiliki komplikasi yang tidak perlu harus memeriksanya sendiri.

Sebagian besar perpustakaan tidak akan pernah memiliki kinerja seperti ini.



DomC juga memimpin dalam grafik dengan memori. Fine-Grained Solid mengungguli VDOM ivi dalam hal konsumsi memori.

Menariknya, perpustakaan ini tidak jauh lebih buruk daripada vanillaJS, terlepas dari metode apa pun. Mereka semua sangat cepat.

Ukuran bundel


Akhirnya, saya ingin menyentuh pada ukuran bungkusan itu. Banyak tes nyata hanya berfokus pada metrik ini. Ya, ukuran bundel itu penting dan memiliki korelasi langsung dengan kinerja, tetapi apa bedanya? Saya menduga kompleksitas kode lebih penting daripada ukuran.



Kesimpulan


Seperti biasa, hasil dalam grafik seperti itu tidak pernah sepenuhnya meyakinkan. Proses itu sendiri dan kesimpulan yang kita buat penting. Dalam hal ini, kita melihat bahwa DOM itu sendiri merupakan hambatan besar dalam hal kinerja. Sedemikian rupa sehingga tidak ada teknik yang jelas untuk mengelaknya.


Christoper Lambert sebagai The Highlander

Tidak, tidak sesederhana itu. Baik DOM maupun VDOM tidak lambat. Tapi saya percaya bahwa mereka layak satu sama lain. Saya akui bahwa retorika VDOM Performance React membawa saya pada pemikiran-pemikiran ini. Ketidaktahuan pendapat tentang topik ini sangat menyebalkan.

Klaim bahwa VDOM lambat adalah karena kesadaran yang buruk. Rendering VDOM dan menghitung perbedaan dalam keadaan adalah komplikasi dibandingkan dengan tidak melakukannya. Tetapi apakah absennya bisa diukur? Dan bagaimana cara membuat perubahan data?

Saya melihat bahwa ada pengecualian dalam setiap aturan. Secara umum, prakompilasi yang dikombinasikan dengan Fine-Grained dalam kerangka kerja reaktif adalah solusi tercepat. Tapi DomC menunjukkan kinerja tinggi tanpa itu. Metode JS asli, seperti elemen template kloning dengan Tagged Template Literals, mungkin menjadi solusi terbaik untuk menerapkan lit-html dari perusahaan besar (Google). Tapi ini adalah salah satu kerangka kerja paling lambat dalam tabel ini dan bahkan bukan implementasi terbaik dari teknologi ini. Svelte dianggap sebagai perpustakaan tercepat di komunitas, tetapi bahkan tidak dapat bersaing dengan solusi yang disajikan.

Jika pemrograman reaktif menang, ini tidak berarti bahwa semua perpustakaan reaktif cepat atau metrik berarti segalanya. Terlepas dari perbandingan mendalam dalam artikel ini, saya berpikir bahwa pada kenyataannya ada perpustakaan cepat dan lebih lambat. Bahkan jika kita menemukan teknologi super, kita masih akan menghadapi keterbatasannya.

Hasil pengujian semua perpustakaan dalam satu tabel:


All Articles