欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用imba.io框架得到比 vue 快50倍的性能基準

 更新時間:2019年06月17日 10:48:43   作者:jump__jump  
imba 是一種新的編程語言,可以編譯為高性能的 JavaScript。可以直接用于 Web 編程(服務(wù)端與客戶端)開發(fā)。這篇文章主要介紹了使用imba.io框架,得到比 vue 快50倍的性能基準,需要的朋友可以參考下

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

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

imba 簡單介紹

imba 是一種新的編程語言,可以編譯為高性能的 JavaScript??梢灾苯佑糜?Web 編程(服務(wù)端與客戶端)開發(fā)。

下面是語法:

// 自定義標簽
tag App
  // 屬性
  prop items
  // 方法定義
  def addItem
    if @input.value
      items.push(title: @input.value)
      @input.value = ""
  def toggleItem item
    item:completed = !item:completed
// 掛載 Imba.mount(element, into) 
// 如果沒有第二個參數(shù),默認掛載到 document.body 上面
Imba.mount <App.vbox items=[] ->
  <form.bar :submit.prevent.addItem>
    <input@input>
    <button> 'add'
  <ul> for item in items
    <li .done=item:completed :tap.toggleItem(item)> item:title

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

imba 框架極速的性能基礎(chǔ)

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

理論基礎(chǔ)

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

HTML DOM 是瀏覽器定義了訪問和操作 HTML 文檔的標準方法。但是操作 DOM 的接口是 JavaScript。但是瀏覽器通常會把 js 引擎和渲染引擎分開實現(xiàn)。也就是頁面實際渲染部分是和解析js部分分開的。

借著《高性能的 JavaScript》話說,如果把 DOM 和 js 各自想象為島嶼。他們需要一座橋進行溝通。所以每一次執(zhí)行 DOM 操作就過橋一次。

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

那么 memoized DOM 又是怎么做的呢?把 DOM 節(jié)點的控制直接放入內(nèi)存之中。類似于此類優(yōu)化.

function getEls(sel) {
  // 設(shè)置緩存
  if (!getEls.cache) getEls.cache = {};
  
  // 如果緩存中存在 el,直接返回 
  if (getEls.cache[sel]) {
    return getEls.cache[sel];
  }

  // 沒有去通過 DOM 查詢
  const r = document.querySelectorAll(sel || '☺'),
    length = r.length;
  
  // 緩存并返回元素節(jié)點
  return getEls.cache[sel] = (length == 1) ? r[0] : r;
}

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

// 直接通過 querySelectorAll 獲取節(jié)點
function getElsByDocument(sel) {
  const r = document.querySelectorAll(sel || '☺'),
    length = r.length;
  return length == 1 ? r[0] : r;
}

// 簡單性能測試
function simplePerTest(fn, el) {
  const fnName = fn.name
  console.time(fnName)
  
  // 2000 次操作
  for(let i = 0,len = 2000; i < len; i++) {
    fn(el)
  }
  console.timeEnd(fnName)
}

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

框架實踐

實例如下所示:

tag Component
  def render
    <self>
      <h1.title> "Welcome"
      <p.desc> "I am a component"

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

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

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

// 在第一次調(diào)用時候 $.$不存在 $.$會等于 后面的數(shù)組
// 第二次調(diào)用 $.$ 是存在的,無運行時消耗
$.$ = $.$ || 數(shù)組

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

tag.prototype.setChildren = function (new$,typ){

  var old = this._tree_;
  
  if (new$ === old && (!(new$) || new$.taglen == undefined)) {
    return this;
  };
  if (!old && typ != 3) {
    this.removeAllChildren();
    appendNested(this,new$);
  } else if (typ == 1) {
    var caret = null;
    for (var i = 0, items = iter$(new$), len = items.length; i < len; i++) {
      caret = reconcileNested(this,items[i],old[i],caret);
    };
  } else if (typ == 2) {
    return this;
  } else if (typ == 3) {
    var ntyp = typeof new$;
      
    if (ntyp != 'object') {
      return this.setText(new$);
    };
      
    if (new$ && new$._dom) {
      this.removeAllChildren();
      this.appendChild(new$);
    } else if (new$ instanceof Array) {
      if (new$._type == 5 && old && old._type == 5) {
        reconcileLoop(this,new$,old,null);
      } else if (old instanceof Array) {
        reconcileNested(this,new$,old,null);
      } else {
        this.removeAllChildren();
        appendNested(this,new$);
      };
    } else {
      return this.setText(new$);
    };
  } else if (typ == 4) {
    reconcileIndexedArray(this,new$,old,null);
  } else if (typ == 5) {
    reconcileLoop(this,new$,old,null);
  } else if ((new$ instanceof Array) && (old instanceof Array)) {
    reconcileNested(this,new$,old,null);
  } else {
    // what if text?
    this.removeAllChildren();
    appendNested(this,new$);
  };  
  this._tree_ = new$;
  return this;
};

如果我們使用了動態(tài)屬性。代碼如下

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

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

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

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

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

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

瀏覽器的運行機制

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

真實世界的內(nèi)存限制

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

imba 框架與瀏覽器的暢想

Google io 大會 chorme Portals 技術(shù)

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

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

 js引擎 與 渲染引擎的關(guān)聯(lián)

在之前,瀏覽器 js引擎和渲染引擎是沒有任何關(guān)聯(lián)的,我們?nèi)憚赢嬛荒芡ㄟ^ setTimeout 或者 setInterval,更加沒有辦法知道瀏覽器什么時候處于空閑狀態(tài),但是隨著時間的發(fā)展,我們可以通過 requestAnimationFrame 和 requestIdleCallback。requestAnimationFrame 要求瀏覽器在下次重繪之前調(diào)用指定的回調(diào)函數(shù)更新動畫。requestIdleCallback方法將在瀏覽器的空閑時段期間對要調(diào)用的隊列函數(shù)進行執(zhí)行。

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

相關(guān)文章

  • vue組件系列之TagsInput詳解

    vue組件系列之TagsInput詳解

    TagsInput 是一種可編輯的輸入框,通過回車或者分號來分割每個標簽,用回退鍵刪除上一個標簽。這篇文章主要介紹了vue組件TagsInput的相關(guān)知識,需要的朋友可以參考下
    2020-05-05
  • 基于vue編寫一個月餅連連看游戲

    基于vue編寫一個月餅連連看游戲

    中秋節(jié)快要到啦,我們一起用Vue創(chuàng)建一個簡單的連連看游戲,連連看大家一定都玩過吧,通過消除相同的圖案來清理棋盤,小編將一步步引導(dǎo)大家完成整個游戲的制作過程,讓我們開始吧,一起為中秋節(jié)增添一些互動和娛樂
    2023-09-09
  • vue3中<script?setup>?和?setup函數(shù)的區(qū)別對比

    vue3中<script?setup>?和?setup函數(shù)的區(qū)別對比

    這篇文章主要介紹了vue3中<script?setup>?和?setup函數(shù)的區(qū)別,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-04-04
  • vue3 teleport的使用案例詳解

    vue3 teleport的使用案例詳解

    這篇文章主要介紹了vue3 teleport的使用demo,本文通過實例代碼給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-11-11
  • Vue關(guān)閉當前彈窗頁面的兩種方式

    Vue關(guān)閉當前彈窗頁面的兩種方式

    這篇文章主要給大家介紹了關(guān)于Vue關(guān)閉當前彈窗頁面的兩種方式,這是最近項目中遇到的一個需求,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-07-07
  • 使用vue和element-ui上傳圖片及視頻文件方式

    使用vue和element-ui上傳圖片及視頻文件方式

    這篇文章主要介紹了使用vue和element-ui上傳圖片及視頻文件方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-08-08
  • Vue實現(xiàn)用戶自定義字段顯示數(shù)據(jù)的方法

    Vue實現(xiàn)用戶自定義字段顯示數(shù)據(jù)的方法

    今天小編就為大家分享一篇Vue實現(xiàn)用戶自定義字段顯示數(shù)據(jù)的方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2018-08-08
  • vue路由傳參-如何使用encodeURI加密參數(shù)

    vue路由傳參-如何使用encodeURI加密參數(shù)

    這篇文章主要介紹了vue路由傳參-如何使用encodeURI加密參數(shù),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • vue組件實現(xiàn)首次加載就觸發(fā)watch

    vue組件實現(xiàn)首次加載就觸發(fā)watch

    這篇文章主要介紹了vue組件實現(xiàn)首次加載就觸發(fā)watch方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-07-07
  • nuxt.js中間件實現(xiàn)攔截權(quán)限判斷的方法

    nuxt.js中間件實現(xiàn)攔截權(quán)限判斷的方法

    這篇文章主要介紹了nuxt.js中間件實現(xiàn)攔截權(quán)限判斷的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-11-11

最新評論