成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

震驚,使用imba框架,得到比 vue 快50倍的性能基準

開發 前端
imba 是一種新的編程語言,可以編譯為高性能的 JavaScript。可以直接用于 Web 編程(服務端與客戶端)開發。

 我是標題黨嗎?是,但也不是。以圖為證。

上圖表示了vue, react 以及 imba 在 todo 這個項目中擁有60個 todoItem 不同進行 crud 操作的表現。可以看到 imba 達到了每秒操作5w次以上。如果你也想試一試該測試,可以訪問 Todos Bench。測試使用的是 Benchmark.js。

imba 簡單介紹

imba 是一種新的編程語言,可以編譯為高性能的 JavaScript。可以直接用于 Web 編程(服務端與客戶端)開發。

下面是語法: 

  1. // 自定義標簽  
  2. tag App  
  3.     // 屬性  
  4.     prop items  
  5.     // 方法定義  
  6.     def addItem  
  7.         if @input.value  
  8.             items.push(title: @input.value)  
  9.             @input.value = ""  
  10.     def toggleItem item  
  11.         item:completed = !item:completed  
  12. // 掛載 Imba.mount(element, into)   
  13. // 如果沒有第二個參數,默認掛載到 document.body 上面  
  14. Imba.mount <App.vbox items=[] ->  
  15.     <form.bar :submit.prevent.addItem>  
  16.         <input@input>  
  17.         <button> 'add'  
  18.     <ul> for item in items  
  19.         <li .done=item:completed :tap.toggleItem(item)> item:title 

可以看出作者喜歡 ruby 以及 pug,偏向于縮進類風格(個人并不是很喜歡這種語法風格)。具體語法可以參考 imba 文檔。當然了,因為可以編譯成js,所以服務端編譯成 js 進行node開發也是可以實現的。

imba 框架極速的性能基礎

任何一個實現的性能優化都有其理論基礎,那么 imba 性能那么快的基礎究竟是什么呢?答案也就是 memoized DOM(記憶DOM)。

理論基礎

瀏覽器的 DOM 操作可以說是瀏覽器最終要的功能,無論框架是基于虛擬 DOM 或者是真實 DOM,最終離不開操作 DOM 對象。

HTML DOM 是瀏覽器定義了訪問和操作 HTML 文檔的標準方法。但是操作 DOM 的接口是 JavaScript。但是瀏覽器通常會把 js 引擎和渲染引擎分開實現。也就是頁面實際渲染部分是和解析js部分分開的。 借著《高性能的 JavaScript》話說,如果把 DOM 和 js 各自想象為島嶼。他們需要一座橋進行溝通。所以每一次執行 DOM 操作就過橋一次。

那我們先談談虛擬DOM,虛擬DOM 的性能提升在于是將 DOM 的對比放在了js層。進而通過對比不同之處來進行實際的 DOM 渲染。也就是說,其實虛擬DOM 并沒有“實際”的性能收益,橋仍舊還在那邊。僅僅在 js引擎需要過橋的那邊找到了一位聰明睿智的大叔,對過橋的人和過橋的貨物進行優化和限制(虛擬DOM 高性能的diff算法,狀態批量更新)。

那么 memoized DOM 又是怎么做的呢?把 DOM 節點的控制直接放入內存之中。類似于此類優化。 

  1. function getEls(sel) {  
  2.     // 設置緩存  
  3.     if (!getEls.cache) getEls.cache = {};    
  4.     // 如果緩存中存在 el,直接返回   
  5.     if (getEls.cache[sel]) {  
  6.         return getEls.cache[sel];  
  7.     }  
  8.     // 沒有去通過 DOM 查詢  
  9.     const r = document.querySelectorAll(sel || '☺'),  
  10.         length = r.length;    
  11.     // 緩存并返回元素節點  
  12.     return getEls.cache[sel] = (length == 1) ? r[0] : r;  

我們可以測試一下。這里我寫一個 getElsByDocument 以及 simplePerTest。 

  1. // 直接通過 querySelectorAll 獲取節點  
  2. function getElsByDocument(sel) {  
  3.     const r = document.querySelectorAll(sel || '☺'),  
  4.         length = r.length;  
  5.     return length == 1 ? r[0] : r;  
  6.  
  7. // 簡單性能測試  
  8. function simplePerTest(fn, el) {  
  9.     const fnfnName = fn.name  
  10.     console.time(fnName)    
  11.     // 2000 次操作  
  12.     for(let i = 0,len = 2000; i < len; i++) {  
  13.         fn(el)  
  14.     }  
  15.     console.timeEnd(fnName)  

這個緩存的節點查詢可要比 querySelectorAll 快了 140倍以上啊,隨著 img 節點越多,得到的性能提升也越高啊。如果imba 框架中所有的節點都在內存中呢?同時,我們還會得到一個 js 運行時優化( GC 的大量減少),因為虛擬DOM 要維護一個樹,在進行多次 crud 之后就會產生大量無用對象從而導致瀏覽器進行 GC,而 memoized DOM 在多次 crud 不會進行多次 GC。(可能會在渲染引擎中 GC?但我感覺渲染引擎中GC 要比JS 中影響要小很多。挖個坑,研究完渲染引擎再來探討一下)

框架實踐

實例如下所示: 

  1. tag Component  
  2.     def render  
  3.         <self>  
  4.             <h1.title> "Welcome"  
  5.             <p.desc> "I am a component" 

上面的自定義組件會編譯成下面的js: 

  1. var Component = Imba.defineTag('Component', function(tag){  
  2.     tag.prototype.render = function (){  
  3.         var $ = this.$;  
  4.         // 返回dom  
  5.         return this.setChildren($.$ = $.$ || [  
  6.             createElement('h1',$,0,this).flag('title').setText("Welcome"),  
  7.             createElement('p',$,1,this).flag('desc').setText("I am a component")  
  8.         ]).synced();  
  9.     };  
  10. }); 

仔細觀察一下這里的函數,你會看到該組件在***次調用渲染時,將使用 createElement 創建兩個子節點,并設置它們的屬性并且緩存。第二次或者***萬次調用時,children-array將被緩存,不會發生任何調用。 

  1. // 在***次調用時候 $.$不存在  $.$會等于 后面的數組  
  2. // 第二次調用 $.$ 是存在的,無運行時消耗  
  3. $.$ = $.$ || 數組 

其中查看源碼,我們可以看到 setChildren 函數都是對真實DOM 進行了操作。獲取之前的DOM節點進行一系列操作后將當前節點返回并緩存。 

  1. tag.prototype.setChildren = function (new$,typ){  
  2.     var old = this._tree_;    
  3.     if (new$ === old && (!(new$) || new$.taglen == undefined)) {  
  4.         return this;  
  5.     };  
  6.     if (!old && typ != 3) {  
  7.         this.removeAllChildren();  
  8.         appendNested(this,new$);  
  9.     } else if (typ == 1) {  
  10.         var caret = null 
  11.         for (var i = 0items = iter$(new$), len = items.length; i < len; i++) {  
  12.             caret = reconcileNested(this,items[i],old[i],caret);  
  13.         };  
  14.     } else if (typ == 2) {  
  15.         return this;  
  16.     } else if (typ == 3) {  
  17.         var ntyp = typeof new$;         
  18.          if (ntyp != 'object') {  
  19.             return this.setText(new$);  
  20.         };           
  21.          if (new$ && new$._dom) {  
  22.             this.removeAllChildren();  
  23.             this.appendChild(new$);  
  24.         } else if (new$ instanceof Array) {  
  25.             if (new$._type == 5 && old && old._type == 5) {  
  26.                 reconcileLoop(this,new$,old,null);  
  27.             } else if (old instanceof Array) {  
  28.                 reconcileNested(this,new$,old,null);  
  29.             } else {  
  30.                 this.removeAllChildren();  
  31.                 appendNested(this,new$);  
  32.             };  
  33.         } else {  
  34.             return this.setText(new$);  
  35.         };  
  36.     } else if (typ == 4) {  
  37.         reconcileIndexedArray(this,new$,old,null);  
  38.     } else if (typ == 5) {  
  39.         reconcileLoop(this,new$,old,null);  
  40.     } else if ((new$ instanceof Array) && (old instanceof Array)) {  
  41.         reconcileNested(this,new$,old,null);  
  42.     } else {  
  43.         // what if text?  
  44.         this.removeAllChildren();  
  45.         appendNested(this,new$);  
  46.     };    
  47.     this._tree_ = new$;  
  48.     return this;  
  49. }; 

如果我們使用了動態屬性。代碼如下: 

  1. tag Component  
  2.     def render  
  3.         <self>  
  4.             <h1.title> "Welcome"  
  5.             # 有 50% 幾率 擁有 red class  
  6.             <p.desc .red=(Math.random > 0.5)> "IMBA" 

可以得到如下代碼,詳細查看可以看出,imba 提取了可變量,放入了 synced 函數中,每次渲染中只會執行 synced 里面的數據,所以依然會得到極高的渲染速度。 

  1. var Component = Imba.defineTag('Component', function(tag){  
  2.     tag.prototype.render = function (){  
  3.         var $ = this.$;  
  4.         return this.setChildren($.$ = $.$ || [  
  5.             _1('h1',$,0,this).flag('title').setText("Welcome"),  
  6.             _1('p',$,1,this).flag('desc').setText("Roulette")  
  7.         ],2).synced((  
  8.             $[1].flagIf('red',Math.random() > 0.5)  
  9.         ,true));  
  10.     };  
  11. }); 

精確的抽取不可變量,然后無需虛擬DOM 計算,同時對于真實DOM 還進行了緩存,我們可以看出 memoized DOM 與 虛擬DOM 不同,memoized DOM 是具有實際的性能收益。

imba 框架“虛假”的性能測試

我們在上面看到了 imba 框架的理論基礎,那么他是否真的比vue快50倍?當然不是,這也就是在上面說我是標題黨的原因。

瀏覽器的運行機制

瀏覽器本身只能達到 60 fps( 1 秒刷新了60次 )。當然了,其實對于體驗而言,60fps的體驗已經差不多夠用了,也就是瀏覽器渲染上大概需要 17ms 去渲染一次。事實上無論是每秒操作dom 5w次還是 1000次,瀏覽器渲染引擎也只會記錄當前的臟數據。然后在需要渲染時候再進行重繪與重排。

真實世界的內存限制

面對 memoized DOM 的緩存優化以及更少 GC 帶來的運行時提升,我們需要更多內存來對每一個 dom節點進行緩存。這個在初始化渲染時有大量的消耗。同時我們的瀏覽器執行速度和渲染速度已經足夠快了,虛擬DOM已經完全夠用了。

imba 框架與瀏覽器的暢想

Google io 大會 chorme Portals 技術

單頁應用程序(Single Page Applications,SPA)提供了很好的頁面交互,但代價是構建的復雜性更高,多頁面應用程序(Multi-page Applications,MPA)更容易構建,但最終會在頁面之間出現空白屏幕。

Portals 結合了這兩者的優勢,主要用于改進網頁交互體驗,目標是無縫導航。它類似于 iframe ,內嵌在網頁上,但可以導航到頁面內容上。用戶在一個頁面跳轉另一個內容時,雖然 URL 相應地發生變化,但是不需要打開另一個窗口,此時該內容標記的 Portals 會變成原來頁面的***頁面,同時原來頁面在其后保持主進程地位。現場演示了這對于購物體驗的極大便利,此外還有對漫畫這類單頁面應用的演示。

[[268439]]

js引擎 與 渲染引擎的關聯

在之前,瀏覽器 js引擎和渲染引擎是沒有任何關聯的,我們去寫動畫只能通過 setTimeout 或者 setInterval,更加沒有辦法知道瀏覽器什么時候處于空閑狀態,但是隨著時間的發展,我們可以通過 requestAnimationFrame 和 requestIdleCallback。requestAnimationFrame 要求瀏覽器在下次重繪之前調用指定的回調函數更新動畫。requestIdleCallback方法將在瀏覽器的空閑時段期間對要調用的隊列函數進行執行。

那么內置DOM 操作是否能夠在js引擎中,是否能夠減少過橋的性能消耗或者完全把橋打通。讓我們拭目以待。

鼓勵一下

如果你覺得這篇文章不錯,希望可以給與我一些鼓勵,在我的 github 博客下幫忙 star 一下。 博客地址:https://github.com/wsafight/personBlog

 

責任編輯:龐桂玉 來源: 中國IDC圈
相關推薦

2022-06-08 09:20:58

Python基準測試編程語言

2022-10-27 08:31:31

架構

2021-05-06 10:52:09

Java Spring Bo框架

2024-03-26 10:13:54

日志引擎SigLens

2021-08-03 06:57:36

Protocol Bu平臺Json

2023-04-07 08:17:39

fasthttp場景設計HTTP

2022-04-26 15:24:03

開源框架

2012-07-31 09:02:49

Apworks

2021-01-04 09:58:46

5G6G運營商

2019-10-14 09:50:52

KeyDBRedis中間件

2021-07-28 14:20:13

正則PythonFlashText

2022-11-02 08:12:47

TurbopackVite

2015-11-25 14:39:51

LiFiWiFi

2021-06-11 09:21:20

開源SQL Parser詞法語法分析器

2022-12-05 14:50:53

2024-03-08 07:58:13

QPShttpsync

2019-08-06 17:19:22

開源技術 趨勢

2022-03-19 10:26:48

Linuxapt 命令

2020-02-09 16:18:45

Redis快 5 倍中間件

2011-06-29 09:31:58

3G4G5G
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 美日韩免费视频 | 黄网站在线播放 | 欧美精品一区二区三区蜜臀 | 日韩一区二区成人 | 欧美精品一区二区三区一线天视频 | 久久亚洲国产精品日日av夜夜 | 国产91色在线 | 亚洲 | 99久久精品一区二区成人 | 麻豆国产一区二区三区四区 | 日本a级大片 | 亚洲欧美少妇 | 欧美999| 亚洲综合五月天婷婷 | 99精品欧美一区二区三区综合在线 | 天天干天天操天天看 | 精品欧美黑人一区二区三区 | 国产成人福利在线观看 | 成人精品一区二区三区中文字幕 | 人人叉 | 久久久国产精品 | 国产激情一区二区三区 | 国产精品欧美一区二区 | 日韩在线精品 | 亚洲国产精品一区二区三区 | 国产亚洲欧美在线 | 日韩中文字幕在线观看视频 | 中文在线a在线 | 一级看片免费视频囗交动图 | 国产在线中文 | 99re在线视频 | 色偷偷人人澡人人爽人人模 | 国产精品久久免费观看 | 91精品亚洲 | 亚洲国产成人精品在线 | 在线看黄免费 | 国产欧美在线观看 | 91精品一区二区三区久久久久久 | 中文在线一区二区 | 国产在线高清 | 一区二区三区日韩 | 国产精品高潮呻吟久久av黑人 |