Mengapa konsep React tentang Virtual DOM dikatakan lebih berkinerja daripada pengecekan model kotor?

372

Saya melihat React dev talk at ( Pete Hunt: React: Rethinking best practices - JSConf EU 2013 ) dan pembicara menyebutkan bahwa pengecekan model yang kotor bisa lambat. Tapi bukankah menghitung perbedaan antara DOM virtual sebenarnya bahkan lebih sedikit performanya karena DOM virtual, dalam banyak kasus, harus lebih besar dari model?

Saya sangat suka kekuatan potensial dari DOM Virtual (terutama rendering sisi-server) tetapi saya ingin mengetahui semua pro dan kontra.

Daniil
sumber
Saya pikir Anda bisa menyebutkan pembicaraan ini juga youtube.com/watch?v=-DX3vJiqxm4 di mana ia secara khusus berbicara tentang tolok ukur.
inafalcao

Jawaban:

493

Saya penulis utama modul virtual-dom , jadi saya mungkin bisa menjawab pertanyaan Anda. Sebenarnya ada 2 masalah yang perlu diselesaikan di sini

  1. Kapan saya melakukan render ulang? Jawab: Ketika saya amati bahwa datanya kotor.
  2. Bagaimana cara merender ulang secara efisien? Jawaban: Menggunakan DOM virtual untuk menghasilkan patch DOM nyata

Dalam Bereaksi, masing-masing komponen Anda memiliki status. Keadaan ini seperti diamati yang mungkin Anda temukan di KO atau pustaka gaya MVVM lainnya. Intinya, Bereaksi tahu kapan harus merender ulang adegan karena ia bisa mengamati kapan data ini berubah. Pengecekan yang kotor lebih lambat daripada yang bisa diamati karena Anda harus melakukan polling data secara berkala dan memeriksa semua nilai dalam struktur data secara rekursif. Sebagai perbandingan, menetapkan nilai pada negara akan memberi sinyal kepada pendengar bahwa beberapa negara telah berubah, sehingga Bereaksi hanya dapat mendengarkan untuk acara perubahan pada negara dan mengantri rendering ulang.

DOM virtual digunakan untuk rendering ulang DOM secara efisien. Ini tidak benar-benar terkait dengan kotor memeriksa data Anda. Anda dapat merender ulang menggunakan DOM virtual dengan atau tanpa pemeriksaan kotor. Anda benar bahwa ada beberapa overhead dalam menghitung perbedaan antara dua pohon virtual, tetapi perbedaan DOM virtual adalah tentang memahami apa yang perlu diperbarui di DOM dan bukan apakah data Anda telah berubah atau tidak. Sebenarnya, algoritma diff adalah pemeriksa kotor itu sendiri tetapi digunakan untuk melihat apakah DOM kotor.

Kami bertujuan membuat ulang pohon virtual hanya ketika kondisi berubah. Jadi menggunakan diamati untuk memeriksa apakah negara telah berubah adalah cara yang efisien untuk mencegah rendering ulang yang tidak perlu, yang akan menyebabkan banyak perbedaan pohon yang tidak perlu. Jika tidak ada yang berubah, kami tidak melakukan apa pun.

DOM virtual itu bagus karena memungkinkan kita menulis kode kita seolah-olah kita sedang merender ulang seluruh adegan. Di belakang layar, kami ingin menghitung operasi tambalan yang memperbarui DOM agar terlihat seperti yang kami harapkan. Jadi walaupun algoritma DOM diff / patch virtual mungkin bukan solusi optimal , ini memberi kami cara yang sangat bagus untuk mengekspresikan aplikasi kami. Kami hanya menyatakan dengan tepat apa yang kami inginkan dan Bereaksi / virtual-dom akan mencari cara untuk membuat adegan Anda terlihat seperti ini. Kami tidak harus melakukan manipulasi DOM manual atau bingung tentang keadaan DOM sebelumnya. Kami juga tidak perlu merender ulang seluruh adegan, yang bisa jadi jauh lebih efisien daripada menambalnya.

Matt Esch
sumber
1
Apakah Bereaksi melakukan pengecekan kotor pada alat peraga komponen? Saya bertanya karena tidak ada fungsi setProps ().
bennlich
1
apa yang akan menjadi contoh seperti itu unnecessary re-renders?
vsync
9
Ketika Anda mengatakan "Jadi, sementara algoritma DOM diff / patch virtual mungkin bukan solusi optimal", apakah Anda memiliki solusi teoritis yang lebih optimal?
CMCDragonkai
3
Ini sepertinya tidak menjawab pertanyaan. Bereaksi mengharuskan Anda untuk menggunakan setState untuk memberi sinyal bahwa keadaan telah berubah. Jika Anda bisa melakukannya, this.state.cats = 99Anda masih perlu memeriksa kotor untuk memeriksa perubahan model, seperti halnya kotor Angular memeriksa pohon $ scope. Ini bukan perbandingan kecepatan kedua teknik, itu hanya pernyataan bahwa Bereaksi tidak melakukan pemeriksaan kotor karena memiliki setter gaya Backbone sebagai gantinya.
superluminary
133

Baru-baru ini saya membaca artikel terperinci tentang React's algorithm di sini: http://calendar.perfplanet.com/2013/diff/ . Dari apa yang saya mengerti, apa yang membuat React cepat adalah:

  • Operasi baca / tulis DOM batch.
  • Pembaruan sub-pohon yang efisien saja.

Dibandingkan dengan pemeriksaan kotor, perbedaan utama IMO adalah:

  1. Pengecekan model kotor : Komponen reaksi secara eksplisit ditetapkan sebagai kotor setiap kali setStatedipanggil, jadi tidak diperlukan perbandingan (data) di sini. Untuk pemeriksaan kotor, perbandingan (dari model) selalu terjadi pada setiap loop intisari.

  2. Pembaruan DOM : Operasi DOM sangat mahal karena memodifikasi DOM juga akan menerapkan dan menghitung gaya, tata letak CSS. Waktu yang dihemat dari modifikasi DOM yang tidak perlu bisa lebih lama dari waktu yang dihabiskan untuk membedakan DOM virtual.

Poin kedua bahkan lebih penting untuk model non-sepele seperti satu dengan jumlah bidang yang besar atau daftar besar. Satu perubahan lapangan dari model kompleks hanya akan menghasilkan operasi yang diperlukan untuk elemen DOM yang melibatkan bidang itu, alih-alih seluruh tampilan / templat.

tungd
sumber
1
Sebenarnya saya telah membaca beberapa artikel juga, jadi saya sekarang (setidaknya secara umum) cara kerjanya, saya hanya ingin mencari tahu mengapa itu bisa lebih efisien daripada memeriksa model yang kotor. Dan 1) Ya, itu tidak membandingkan model tetapi membandingkan dom virtual yang jauh lebih besar 2) Memeriksa model yang kotor memberi kita kemampuan untuk memperbarui hanya apa yang diperlukan juga (seperti yang dilakukan Angular)
Daniil
Saya percaya hanya bagian dari DOM virtual yang sesuai dengan komponen yang diubah yang harus dibandingkan, sementara pengecekan kotor terjadi setiap loop digest, untuk setiap nilai pada setiap cakupan, bahkan jika tidak ada yang berubah. Jika sejumlah besar data berubah, maka Virtual DOM akan kurang efisien, tetapi tidak untuk perubahan data kecil.
tungd
1
Berbicara tentang Angular, karena pengamat juga dapat mengubah keadaan saat dicerna, $scope.$digestdijalankan beberapa kali per siklus digest, jadi ini adalah beberapa kali perbandingan data lengkap dibandingkan satu kali perbandingan pohon DOM virtual parsial.
tungd
4
Sedihnya begitu banyak pengembang pintar yang menemukan "gunungan" trik untuk menangani "lambat" DOM ​​dan sebagainya, alih-alih memfokuskan perhatian gabungan kami untuk hanya memperbaiki peramban itu sendiri dan menghilangkan kelambatan DOM kami sekali dan untuk semua. itu seperti menggunakan semua sumber daya manusia untuk meneliti cara-cara menangani kanker dan meningkatkan kehidupan pasien, alih-alih hanya memperbaiki kanker itu sendiri. Ejekan.
vsync
@vsync DOM perlu menampilkan hal-hal di layar. DOM virtual tidak. Bahkan dengan beberapa DOM berkinerja ideal, membuat DOM virtual akan lebih cepat.
Jehan
75

Saya sangat suka kekuatan potensial dari DOM Virtual (terutama rendering sisi-server) tetapi saya ingin mengetahui semua pro dan kontra.

- OP

Bereaksi bukan satu-satunya perpustakaan manipulasi DOM. Saya mendorong Anda untuk memahami alternatif dengan membaca artikel ini dari Auth0 yang mencakup penjelasan terperinci dan tolok ukur. Saya akan menyoroti di sini pro dan kontra mereka, saat Anda bertanya:

Virtual DOM React.js

masukkan deskripsi gambar di sini

PROS

  • Algoritma "difing" yang cepat dan efisien
  • Banyak frontends (JSX, hyperscript)
  • Cukup ringan untuk dijalankan di perangkat seluler
  • Banyak traksi dan mindshare
  • Dapat digunakan tanpa Bereaksi (yaitu sebagai mesin independen)

Kon

  • Salinan DOM dalam memori penuh (penggunaan memori lebih tinggi)
  • Tidak ada perbedaan antara elemen statis dan dinamis

Glber Ember.js '

masukkan deskripsi gambar di sini

PROS

  • Algoritma difing yang cepat dan efisien
  • Diferensiasi antara elemen statis dan dinamis
  • 100% kompatibel dengan Ember's API (Anda mendapatkan manfaat tanpa pembaruan utama pada kode Anda yang ada)
  • Representasi ringan di memori DOM

Kon

  • Dimaksudkan untuk digunakan hanya di Ember
  • Hanya satu frontend yang tersedia

DOM tambahan

masukkan deskripsi gambar di sini

PROS

  • Pengurangan penggunaan memori
  • API sederhana
  • Mudah diintegrasikan dengan banyak frontend dan kerangka kerja (dimaksudkan sebagai mesin templat backend dari awal)

Kon

  • Tidak secepat perpustakaan lain (ini bisa diperdebatkan, lihat tolok ukur di bawah)
  • Lebih sedikit mindshare dan penggunaan komunitas
falsarella
sumber
Representasi manipulasi DOM ReactJS nampak sedikit aneh bagi saya. DOM virtual ReactJS adalah yang berubah seluruhnya, bukan DOM yang sebenarnya - benar? Saya melihat artikel asli referensi artikel yang dirujuk dan di sini adalah apa yang saya lihat - teropa.info/images/onchange_vdom_change.svg . teropa.info/blog/2015/03/02/…
smile.al.d.way
35

Berikut ini komentar dari anggota tim React Sebastian Markbåge yang memberi penjelasan:

Bereaksi apakah perbedaan pada output (yang merupakan format serializable dikenal, atribut DOM). Ini berarti bahwa data sumber dapat berupa format apa pun. Ini bisa menjadi struktur data yang tidak berubah dan menyatakan bagian dalam penutupan.

Model Angular tidak mempertahankan transparansi referensial dan karenanya inheren bisa berubah. Anda mengubah model yang ada untuk melacak perubahan. Bagaimana jika sumber data Anda adalah data tidak berubah atau struktur data baru setiap saat (seperti respons JSON)?

Pengecekan kotor dan Object.observe tidak berfungsi pada kondisi lingkup penutupan.

Kedua hal ini sangat terbatas pada pola fungsional.

Selain itu, ketika kompleksitas model Anda tumbuh, menjadi semakin mahal untuk melakukan pelacakan kotor. Namun, jika Anda hanya melakukan diffing pada pohon visual, seperti React, maka itu tidak bertambah banyak karena jumlah data yang dapat Anda tampilkan di layar pada titik tertentu dibatasi oleh UI. Tautan Pete di atas mencakup lebih banyak manfaat perf.

https://news.ycombinator.com/item?id=6937668

Sophie Alpert
sumber
2
Sebenarnya tentang paragraf terakhir: seharusnya salah: model lebih besar dari dom virtual karena untuk setiap nilai model ada (dalam kebanyakan kasus) setidaknya satu elemen dom virtual (dan biasanya jauh lebih dari satu). Mengapa saya ingin model yang tidak ditampilkan?
Daniil
2
Mengumpulkan koleksi dalam cache.
kentor
-2

Virtual Dom tidak ditemukan oleh reaksi. Ini adalah bagian dari dom HTML. Ia ringan dan terlepas dari detail implementasi khusus browser.

Kita dapat menganggap DOM virtual sebagai salinan HTML DOM yang lokal dan disederhanakan. Ini memungkinkan React untuk melakukan komputasinya dalam dunia abstrak ini dan melewati operasi DOM "nyata", seringkali lambat dan khusus browser. Sebenarnya tidak ada perbedaan besar antara DOM dan VIRTUAL DOM.

Di bawah ini adalah poin mengapa Virtual Dom digunakan (sumber Virtual DOM di ReactJS ):

Saat kamu melakukan:

document.getElementById('elementId').innerHTML = "New Value" Following thing happens:
  1. Browser perlu mem-parsing HTML
  2. Ini menghapus elemen turunan dari elemenId
  3. Memperbarui nilai DOM dengan nilai baru
  4. Hitung ulang css untuk orang tua dan anak
  5. Perbarui tata letak yaitu setiap elemen berkoordinasi tepat pada layar
  6. Lintasi pohon render dan cat di tampilan browser

Menghitung ulang CSS dan mengubah layout menggunakan algoritma yang kompleks dan mereka mempengaruhi kinerja.

Serta memperbarui properti DOM yaitu. nilai-nilai. Ini mengikuti suatu algoritma.

Sekarang, anggaplah jika Anda memperbarui DOM 10 kali secara langsung, maka semua langkah di atas akan berjalan satu per satu dan memperbarui algoritma DOM akan membutuhkan waktu untuk memperbarui nilai DOM.

Inilah sebabnya mengapa Real DOM lebih lambat daripada DOM virtual.

Hemant Nagarkoti
sumber
3
Tentang contoh, jika Anda memodifikasi dom secara langsung atau melalui dom virtual, maka akhirnya untuk kedua kasus Anda mengubah dom.
magallanes
Ya dalam kedua kasus kami memperbarui dom tetapi dalam kasus dom virtual itu memperbarui khususnya bahwa kunci (khusus didefinisikan oleh algoritma yang berbeda dari reaksi) bidang atau tag elemen saja. Sedangkan memperbarui pembaruan dom atau menyegarkan seluruh dom sepenuhnya.
Hemant Nagarkoti
11
Saya telah melihat artikel ini dari hackernoon.com/virtual-dom-in-reactjs-43a3fdb1d130 . Mungkin lebih baik menunjukkan sumbernya jika Anda bukan penulisnya.
Jinggang
2
"Ini, itulah sebabnya DOM Nyata lebih lambat daripada DOM virtual." Tidak, Anda salah.
Roecrew