虛擬dom添加虛擬dom_虛擬DOM緩慢。 認識記憶化的DOM

虛擬dom添加虛擬dom

by Sindre Osen Aarsaether

通過Sindre Osen Aarsaether

虛擬DOM緩慢。 符合已記憶的DOM。 (The Virtual DOM is slow. Meet the Memoized DOM.)

超越虛擬DOM和狀態管理 (Moving beyond the Virtual DOM and State Management)

The virtual DOM was a fantastic innovation. It brought about a much more productive way of writing web applications by allowing us to write our views in a declarative manner.

虛擬DOM是一項了不起的創新。 通過允許我們以聲明的方式編寫視圖,它帶來了一種更加高效的Web應用程序編寫方式。

This big benefit has little to do with performance of the initial render. Instead, it is the process of updating the DOM to reflect changes in your state has become much faster.

這個很大的好處與初始渲染的性能無關。 相反,它是更新DOM以反映您狀態變化的過程,變得更快。

This process of bringing the DOM in sync with the state is often referred to as DOM reconciliation.

使DOM與狀態同步的過程通常稱為DOM協調 。

If we had an infinitely fast reconciler, we could vastly simplify our applications by rendering everything on every single frame. The state layer would never need to know about views at all — much less send out events and track which views need to react when certain parts of the state change. The view would always be in sync with the data, no matter what you threw at it.

如果我們有一個無限快的協調器,則可以通過在每個幀上渲染所有內容來極大地簡化我們的應用程序。 狀態層根本不需要了解視圖,更不用說發出事件并跟蹤在狀態的某些部分發生變化時需要響應的視圖。 無論您對視圖進行什么操作,視圖都將始終與數據保持同步。

Sadly, virtual DOM implementations are not infinitely fast. They are, in fact, surprisingly slow. Thankfully, many have jumped on the Immutability? bandwagon, in which case the virtual DOM thanks you! Others wrap all state in observables (e.g. mobx), and keep track of which view depends on what state. This allows you to reconcile only parts of your view, but comes with its own set of drawbacks.

令人遺憾的是,虛擬DOM實現并非無限快。 實際上,它們出奇地慢。 值得慶幸的是,許多人躍躍欲試,在這種情況下,虛擬DOM謝謝您! 其他人則將所有狀態都包裹在可觀察對象(例如mobx)中,并跟蹤哪個視圖取決于哪個狀態。 這使您只能協調部分視圖,但有其自身的缺點。

The biggest issue is that we tend to decide how to manage our application state based on our view layer. What if we could get better performance in a world where the data layer and view layer don’t really know or care about each other?

最大的問題是,我們傾向于根據視圖層決定如何管理應用程序狀態。 如果在一個數據層和視圖層并不真正了解或關心彼此的世界中,我們可以獲得更好的性能怎么辦?

認識記憶化的DOM (Meet the Memoized DOM)

Imba is a programming language for the web. It powers the interactive screencasting platform scrimba.com, of which I am the lead developer. Imba was born to make developing web applications fun again. It features a clean and readable syntax inspired by Ruby. It compiles to readable and performant JavaScript, and works inside the existing ecosystem.

Imba是一種網絡編程語言。 它為交互式截屏平臺scrimba.com提供了動力 ,我是其中的首席開發人員。 Imba的誕生再次使開發Web應用程序變得有趣。 它具有受Ruby啟發的簡潔易讀的語法。 它可以編譯為可讀和高性能JavaScript,并可以在現有的生態系統中運行。

Besides a clean and readable syntax, the biggest benefit of Imba is that it truly treats DOM elements as first-class citizens, on a much deeper level than JSX. It allows you to write views declaratively, yet it does not use a virtual DOM. Instead, Imba compiles views to a memoized DOM, which turns out to be an order of magnitude faster.

除了簡潔易懂的語法外,Imba的最大好處是,它在比JSX更深的層次上真正將DOM元素視為一流的公民。 它允許您聲明性地編寫視圖,但不使用虛擬DOM。 取而代之的是,Imba將視圖編譯為已記憶的DOM,事實證明它快了一個數量級

這個怎么運作 (How it works)

The general idea is that we create lightweight wrappers around DOM elements, and compile declarative views to chains of setters, each modifying the underlying DOM directly.

通常的想法是,我們圍繞DOM元素創建輕量級包裝,并將聲明式視圖編譯為設置器鏈,每個視圖都直接修改基礎DOM。

tag AppView    def render        <self>            <h1.title> "Welcome"            <p.desc .red=(Math.random > 0.5)> "Roulette"

The Imba view above will roughly compile into the following javascript:

上方的Imba視圖將大致編譯為以下javascript:

class AppView extends Imba.Tag {  render() {    var $ = this.$; // inline cache for tag    return this.setChildren($.$ = $.$ || [      Imba.tag('h1',$).flag('title').setText("Welcome"),      Imba.tag('p',$).flag('desc').setText("Roulette")    ]).synced(      $[1].flagIf('red',Math.random() > 0.5)    );  }}

This is a very simple example to illustrate the basic concept. During compilation we split creation and updates into separate branches. The first time render is called for an <AppView> the children will be created and static attributes will be set. On all subsequent calls the only real work we do is flip the className of our <p>. Albeit much more complex, the same concept is used for conditionals, loops, and everything else inside tag trees.

這是一個非常簡單的示例,用于說明基本概念。 在編譯過程中,我們將創建和更新分為單獨的分支。 第一次為<AppVi ew>調用渲染時,將創建子代并設置靜態屬性。 在所有后續調用,我們要做的唯一的真正的工作是翻轉的className? fo烏爾<P>。 盡管非常復雜,但相同的概念用于條件樹,循環以及標簽樹中的所有其他內容。

If you’re interested in how it really works I recommend reading this intro.

如果您對它的實際工作方式感興趣,建議閱讀此介紹 。

基準測試 (Benchmark)

React is fast, they said. React is fast enough, they said. React Fiber will be fast enough, they said.
他們說,React很快。 他們說,React足夠快。 他們說,React Fiber將足夠快。

Most benchmarks test things like “insert/shuffle/remove 1000 rows”. This gives little indication about real-world performance. When there are hundres of changes, most of the difference is eaten up by actual DOM mutations, repainting, etc. It fails to measure the most important metric.

大多數基準測試都會測試“插入/隨機播放/刪除1000行”之類的內容。 這幾乎沒有提供有關實際性能的指示。 當存在數百種變化時,大多數差異會被實際的DOM突變,重繪等吞噬掉。它無法衡量最重要的指標。

If you truly want to test the performance of DOM reconciliation, you need to look at how quickly the implementation brings the DOM in sync with the state, especially when there are few/no changes.

如果您確實想測試DOM協調的性能,則需要查看實現使DOM與狀態同步的速度, 尤其是在更改很少/沒有更改的情況下

So, to capture a realistic view of the reconciler performance, we could change a small part of the application state in each iteration, and then measure the time it takes to forcefully bring the view in sync with this changed state. The view should not be listening to any part of the state, and the state should not need to notify anyone whether it has changed.

因此,為了捕獲協調器性能的真實視圖,我們可以在每次迭代中更改應用程序狀態的一小部分,然后測量將視圖強制與此更改狀態同步所需的時間。 該視圖不應監聽狀態的任何部分,并且該狀態不需要通知任何人它是否已更改。

This benchmark steps through a deterministic sequence of state alterations, doing at most one change per iteration. We are measuring the time it takes to reconcile the whole application view after:

該基準測試逐步執行確定性的狀態更改序列, 每次迭代最多進行一次更改 。 在以下情況下,我們正在測量協調整個應用程序視圖所需的時間:

  1. Toggling the completion of a task

    切換任務的完成
  2. Removing a task

    刪除任務
  3. Inserting a task

    插入任務
  4. Renaming a task

    重命名任務
  5. Doing nothing

    什么也不做

結果 (Results)

Running the benchmark on an iMac (4GHz i7) yields the following results:

在iMac(4GHz i7)上運行基準測試會產生以下結果:

Safari 11 (Safari 11)

  • Imba 1.3: 360458 ops / sec

    Imba 1.3: 每秒360458次操作

  • React 16.2: 9752 ops / sec — 36.96x slower

    React 16.2: 9752操作/秒- 慢36.96倍

  • Vue 2.5: 8719 ops / sec — 41.34x slower

    Vue 2.5:每秒8719次操作- 慢41.34倍

Chrome65 (Chrome 65)

  • Imba 1.3: 282484 ops / sec

    Imba 1.3: 282484次操作/秒

  • React 16.2: 8882 ops / sec — 31.81x slower

    React 16.2: 8882次操作/秒- 慢31.81倍

  • Vue 2.5: 8103 ops / sec — 34.86x slower

    Vue 2.5:每秒8103次操作- 慢34.86倍

Firefox 58 (Firefox 58)

  • Imba 1.3: 234334 ops / sec

    Imba 1.3: 每秒234334次操作

  • React 16.2: 5075 ops / sec — 46.17x slower

    React 16.2: 5075次操作/秒- 慢46.17倍

  • Vue 2.5: 3119 ops / sec — 75.13x slower

    Vue 2.5:每秒3119次操作- 慢75.13倍

This seems outrageous right? Surely, it cannot be right.

這似乎太離譜了吧? 當然,這是不對的。

  • All implementations are really reconciling on every step.

    所有實現真正和解的每一步。

  • All implementations are blocking, synchronous, and deterministic.

    所有實現都是阻塞,同步和確定性的。
  • All implementations are performing the same amount of DOM mutations.

    所有實現都執行相同數量的DOM突變。
  • Yes, we are using the minified production build of React. The development version is 200x slower than Imba on the same test.

    是的,我們使用的是最小化的React生產版本。 在同一測試中,開發版本比Imba 慢200倍。

  • The memoized DOM creates practically no garbage during an iteration, uses less memory overall, and is conceptually very simple.

    備注DOM在迭代過程中幾乎不產生垃圾,總體上使用較少的內存,并且從概念上講非常簡單。

All the implementations can probably be optimized more. I’m very happy to accept pull-requests at GitHub. To be clear, I have tremendous respect for what React has achieved, and I truly love Vue. Imba has taken a lot of inspiration from it. I suspect it should be possible to compile Vue templates using a similar approach, and would love for someone to give it a go!

所有實現可能都可以進行更多優化。 我很高興在GitHub接受請求請求。 明確地說,我對React所取得的成就深表敬意,并且我真的很喜歡Vue。 Imba從中汲取了很多靈感。 我懷疑應該可以使用類似的方法來編譯Vue模板,并且希望有人可以嘗試一下!

剖析 (Profiling)

Let’s test the raw reconciler performance when there aren’t even any changes. This removes the time spent doing actual DOM mutations from the equation, and gives us a good picture about how much work is going on during reconciliation. The charted CPU profile from Chrome gives a visual indication of how much less work is done with the memoized DOM technique.

當沒有任何變化時,讓我們測試原始調節器性能。 這消除了從等式中進行實際DOM突變所花費的時間,并為我們提供了有關協調期間正在進行的工作量的清晰圖片。 Chrome的圖表CPU配置文件直觀顯示了使用DOM技術的工作量。

英巴1.3 (Imba 1.3)

React16.2 (React 16.2)

Vue 2.5 (Vue 2.5)

可以縮放嗎? (Does it scale?)

“There are A LOT, and I mean, A LOT of small little projects that claim more speed, easier development, but on closer inspection usually lack very important features (such as module life cycle hooks) and, of course without them the performance is higher, but the flexibility to use those libraries beyond a todo list application is limited.”
“有很多,我的意思是,很多小的項目要求更快,更輕松的開發,但是仔細檢查通常會缺少非常重要的功能(例如模塊生命周期掛鉤),當然,如果沒有它們,性能是更高,但是在待辦事項列表應用程序之外使用這些庫的靈活性受到限制。”

This is a quote from someone who read through an early draft of this article, and I would like to tackle it head on. The performance difference is not limited to a simple test, quite the contrary. Imba has been used in production for several years at scrimba.com, but it is still not for the faint of heart. For most developers the massive ecosystems for Vue and React will be hard (and probably unwise) to leave behind. The Imba documentation still leaves a lot to be desired, but we are improving it every day.

這是從閱讀本文初稿的人那里引用的,我想直接解決。 相反,性能差異不僅限于簡單的測試。 Imba已在scrimba.com上用于生產多年,但仍不是出于膽小。 對于大多數開發人員而言,Vue和React的龐大生態系統將很難(可能不明智)落在后面。 Imba文檔仍然有很多不足之處,但是我們每天都在改進它。

有關系嗎? (Does it matter?)

I’m sure you’ve heard that React is fast enough. But fast enough for what? It doesn’t really matter if React was 15% faster, but with an order of magnitude improvement we can start to explore simpler ways to build applications.

我確定您已經聽說過React足夠快。 但是足夠快嗎? React是否快15%并不重要,但是隨著數量級的提高,我們可以開始探索構建應用程序的更簡單方法。

It’s not about the perceived speed, but about what it lets you do. At scrimba.com we don’t worry about keeping the view in sync with the state. We don’t worry about tracking when state has changed. Our data models are not observable. We just render. Whenever. And it’s liberating.

這與感知的速度無關,而與它可以做什么相關。 在scrimba.com,我們不必擔心視圖與狀態保持同步。 我們不必擔心狀態更改的時間。 我們的數據模型是不可觀察的。 我們只是渲染。 每當。 它正在解放。

翻譯自: https://www.freecodecamp.org/news/the-virtual-dom-is-slow-meet-the-memoized-dom-bb19f546cc52/

虛擬dom添加虛擬dom

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392986.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392986.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392986.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

編寫一個字節數的rtu C語言校驗程序,Modbus通信協議中CRC校驗的快速C語言算法

Modbus通信協議中CRC校驗的快速C語言算法2004年第11期            福 建 電 腦  63Modbus通信協議中CRC校驗的快速C語言算法孟開元(西安石油大學計算機學院陜西西安710065)【摘 要】 本文主要討論了Modbus通信協議的RTU幀格式中常用的錯誤校驗方法,即循環冗…

leetcode1319. 連通網絡的操作次數(并查集)

用以太網線纜將 n 臺計算機連接成一個網絡&#xff0c;計算機的編號從 0 到 n-1。線纜用 connections 表示&#xff0c;其中 connections[i] [a, b] 連接了計算機 a 和 b。 網絡中的任何一臺計算機都可以通過網絡直接或者間接訪問同一個網絡中其他任意一臺計算機。 給你這個…

Codeforces 600E Lomsat gelral (樹上啟發式合并)

題目鏈接 Lomsat gelral 占坑……等深入理解了再來補題解…… #include <bits/stdc.h>using namespace std;#define rep(i, a, b) for (int i(a); i < (b); i)typedef long long LL;const int N 600010;int n; int cc[N], col[N], sz[N], son[N]; LL ans[N];vect…

如何讓CloudStack使用KVM創建Windows實例成功識別并掛載數據盤

問題產生背景&#xff1a; 使用CloudStack KVM組合進行資源池納管工作&#xff0c;通過ISO鏡像文件創建了兩個模板&#xff1a; RHEL6U3 64位系統以及WindowsServer2008 R2 SP1 64位系統。然后通過模板創建實例&#xff0c;掛載外接存儲&#xff0c;實例啟動后&#xff0c;通過…

云計算openstack介紹

轉載于:https://www.cnblogs.com/WIU1905/p/11107593.html

C語言Node lt T gt,c語言論壇填空;#includelt;stdio.hgt;# 愛問知識人

填空&#xff1b;#include #include #define N 6typedef struct node {int data;struct node *next;填空&#xff1b;#include #include #define N 6typedef struct node {int data;struct node *next;} NODE;void fun(NODE *h){ NODE *p, *q; int t;/**********found*********…

gitlab設置郵件服務器_如何設置您自己的一次性電子郵件服務器

gitlab設置郵件服務器by Oren Geva由Oren Geva 如何設置您自己的一次性電子郵件服務器 (How To Setup Your Own Disposable Email Server) Disposable email services are online services that provide temporary email addresses for registering or signing up on websites…

leetcode442. 數組中重復的數據

給定一個整數數組 a&#xff0c;其中1 ≤ a[i] ≤ n &#xff08;n為數組長度&#xff09;, 其中有些元素出現兩次而其他元素出現一次。 找到所有出現兩次的元素。 你可以不用到任何額外空間并在O(n)時間復雜度內解決這個問題嗎&#xff1f; 示例&#xff1a; 輸入: [4,3,2…

C語言基礎注意點

一、基礎知識篇 &#xff08;一&#xff09;關鍵字 1&#xff0c;存儲類型 A、auto 聲明自動變量&#xff0c;一般不使用 B、static 聲明靜態變量 C、extern 聲明變量是在其他文件正聲明&#xff08;可看做引用變量&#xff09; D、register 聲明積有器變量 2、常用…

**加密解密基礎、PKI及SSL、創建私有CA**

進程間通信 socket通信 客戶端-->請求--> 路由轉發 --> 服務端&#xff0c;取出資源 --> 封裝為可響應給客戶端的請求報文從接收請求端口發出 SSL/TLS協議的實現 OpenSSL OpenSSL程序組件 1234[rootlocalhost CA]# rpm -ql openssl /usr/lib/libcrypto.so.10 //加…

json 文件打讀取

1。獲取文件路徑 /** BookController.class.getClassLoader().getResource("static/json/book_nav.json").getPath() 獲取當期運行時的項目json文件路徑*/JSONObject json JsonResourceUtils.getJsonObjFromResource(BookController.class.getClassLoader().getReso…

16F877A和24C02通信匯編語言,pic單片機IIC通信讀24C02程序例 16F877A 主頻4M

#define _iic_h_//pic單片機IIC通信初始化函數聲明void iiccsh(void);//pic單片機IIC通信讀外圍設備函數聲明//功能&#xff1a;傳送一個8位地址&#xff0c;返回一個8位數據unsigned char iicread(unsigned char data);//pic單片機IIC通信給外圍器件發送函數聲明//功能&#x…

如何從XMLHttpRequest創建自定義獲取API

What is your worst nightmare?你最可怕的噩夢是什么&#xff1f; That sounded dark, but it’s not a rhetorical question. I really want to know because I am about to tell you mine. Along the way, we will learn some things like how the fetch API works and als…

leetcode637. 二叉樹的層平均值

給定一個非空二叉樹, 返回一個由每層節點平均值組成的數組。示例 1&#xff1a;輸入&#xff1a;3/ \9 20/ \15 7 輸出&#xff1a;[3, 14.5, 11] 解釋&#xff1a; 第 0 層的平均值是 3 , 第1層是 14.5 , 第2層是 11 。因此返回 [3, 14.5, 11] 。/*** Definition for a b…

5.3 上午

觀看英語課程——《戀練有詞》 學習Linux 轉載于:https://www.cnblogs.com/bgd140206110/p/6801164.html

AD庫轉換為KiCAD庫的方法

AD庫轉換為KiCAD庫的方法 參照博主另外一篇文檔&#xff1a; AD轉換為KiCAD的方法&#xff0c;點擊此處轉載于:https://www.cnblogs.com/zhiqiang_zhang/p/11109560.html

遺傳算法求解裝箱問題c語言,求解裝箱問題的遺傳算法-南昌航空大學期刊網.pdf...

求解裝箱問題的遺傳算法-南昌航空大學期刊網1998 2 Journal of Nanchang Institute of Aeronautical Technology 21998方 平    李 娟( 南昌航空工業學院)  ( 西北工業大學): ( Bin Packing) ,, , D( irst it De-creasing) ,: ; ; ;: TP301. 6( )( Bin Packing) , :1 2 …

mysql索引隨記

為什么80%的碼農都做不了架構師&#xff1f;>>> 先了解下Btree&#xff1a;https://my.oschina.net/u/3646190/blog/1593094 為什么每個數據項&#xff0c;即索引字段要盡量的小&#xff0c;比如int占4字節&#xff0c;要比bigint8字節少一半&#xff1f; 通過上面…

leetcode79. 單詞搜索(回溯算法)

給定一個二維網格和一個單詞&#xff0c;找出該單詞是否存在于網格中。 單詞必須按照字母順序&#xff0c;通過相鄰的單元格內的字母構成&#xff0c;其中“相鄰”單元格是那些水平相鄰或垂直相鄰的單元格。同一個單元格內的字母不允許被重復使用。 示例: board [ [‘A’,‘…

react鉤子_迷上了鉤子:如何使用React的useReducer()

react鉤子So the React Conference just happened and as always something new happened. Hooks happened! The React team talked about suspense, lazy loading, concurrent rendering, and hooks :D.因此&#xff0c;React會議剛剛發生&#xff0c;并且一如既往地發生了一些…