Stories

Detail Return Return

純js、v-for、vue函數式組件、vue普通組件性能對比 - Stories Detail

先説結論

  • dom 節點數量對內存影響沒想象中大,js 變量才是內存佔用的元兇
  • 內存佔用及運行性能對比:原生 js < v-for div ≈ v-for 函數式組件 < v-for 普通組件
  • 去虛擬 dom 化框架正在崛起,成為一種新的選擇

dom 節點數量對內存影響沒想象中大(十萬 div 僅佔用 400mb)

  • 測試示例
  • 生成 100,000(十萬)個 div,內存佔用僅 400mb,平均每個 div 佔用內存 400 * 1024 kb / 100,000 = 4kb
  • 注意,這裏內存佔用是靜態狀態內存,即 div 生成完成後等待一會(約1min)內存回收完成後的內存佔用,div 生成過程中會產生中間變量,內存佔用會比靜態時高。
  • 如果短時間多少清空 div 再重新生成,會導致內存佔用變大

組件過多,或許才是 vue 項目內存佔用大、運行慢的原因

分別以「純 js 渲染 div」、「v-for 渲染 div」、「v-for 渲染函數式組件」、「v-for 渲染普通組件」為例做性能對比測試

「純 js 渲染 div」運行示例,對應源碼

  • 10,000(一萬)個 div

    • 渲染耗時:26ms,平均單個div渲染耗時:0.0026ms
  • 100,000(十萬)個 div

    • 渲染耗時:265ms,平均單個div渲染耗時:0.0027ms
  • 100,000(十萬)個 div

    • 佔用內存:528mb,平均單個佔用內存:528 * 1024 / 100,000 = 5.4kb

「v-for 渲染 div」運行示例,對應源碼

  • 10,000(一萬)個 div

    • 使用 key 緩存節點渲染耗時:61ms,平均單個div渲染耗時:0.0061ms
    • 不使用 key 緩存節點渲染耗時:91ms,平均單個div渲染耗時:0.0091ms
  • 100,000(十萬)個 div

    • 使用 key 緩存節點渲染耗時:499ms,平均單個div渲染耗時:0.005ms
    • 不使用 key 緩存節點渲染耗時:286ms,平均單個div渲染耗時:0.0029ms
  • 100,000(十萬)個 div

    • 佔用內存:586mb,平均單個佔用內存:586 * 1024 / 100,000 = 6kb

「v-for 渲染函數式組件」運行示例,對應源碼

  • 10,000(一萬)個 div

    • 使用 key 緩存節點渲染耗時:85ms,平均單個div渲染耗時:0.0085ms
    • 不使用 key 緩存節點渲染耗時:82ms,平均單個div渲染耗時:0.0082ms
  • 100,000(十萬)個 div

    • 使用 key 緩存節點渲染耗時:392ms,平均單個div渲染耗時:0.0039ms
    • 不使用 key 緩存節點渲染耗時:505ms,平均單個div渲染耗時:0.005ms
  • 100,000(十萬)個 div

    • 佔用內存:654mb,平均單個佔用內存:654 * 1024 / 100,000 = 6.7kb

「v-for 渲染普通組件」運行示例,對應源碼

  • 10,000(一萬)個 div

    • 使用 key 緩存節點渲染耗時:122ms,平均單個div渲染耗時:0.0122ms
    • 不使用 key 緩存節點渲染耗時:360ms,平均單個div渲染耗時:0.0325ms
  • 100,000(十萬)個 div

    • 使用 key 緩存節點渲染耗時:918ms,平均單個div渲染耗時:0.0092ms
    • 不使用 key 緩存節點渲染耗時:13881ms(13.8s),平均單個div渲染耗時:0.1388ms
  • 100,000(十萬)個 div

    • 佔用內存:907mb,平均單個佔用內存:907 * 1024 / 100,000 = 9.3kb

通過上述測試可得

純 js 渲染 v-for 渲染 div v-for 渲染函數式組件 v-for 渲染普通組件
一萬div複用key渲染耗時 - 61ms/6.1us 85ms/8.5us 122ms/12.2us
一萬div不復用key渲染耗時 26ms/2.6us 91ms/9.1us 82ms/8.2us 360ms/36us
十萬div複用key渲染耗時 - 286ms/2.9us 392ms/3.9ms 918ms/9.2us
十萬div不復用key渲染耗時 265ms/2.7us 499m/5us 505ms/5us 13881ms/138.8us
十萬div內存佔用 528mb/5.4kb 586mb/6kb 652mb/6.7kb 907mb/9.3kb
  • dom 節點數量對內存影響沒想象中大,10萬 div 佔用內存 400mb(只生成一次),平均單個 div 佔用內存僅 4kb
  • vue 組件對內存佔用較大,僅僅最簡單的 div 組件就需要額外添加 9.3 - 5.4 = 3.9kb 內存,若組件複雜度上升,則內存佔用將進一步增加。成為內存瓶頸
  • vue 函數式組件、v-for div 是否使用 key 緩存節點,對運行耗時變化不大
  • vue 組件是 key 緩存節點,對節點更新性能有很大提升,10萬組件更新,從 13s 耗時優化到 0.9s 耗時,減少近 13 - 0.9 / 13 = 93% 運算耗時
  • vue 組件並非越細越好,顆粒度太細,將導致 vue 組件數量急劇增加,內存佔用急劇增加
  • 純 js 渲染 div 最快,使用 v-for div,v-for 函數式組件的渲染耗時至少是 純 js 渲染耗時的兩倍,這是由於虛擬節點 vnode 需要執行 diff 算法決定的。

去虛擬化正在崛起

既然 vnode 計算如此消耗性能,那可否捨棄 vnode 來提高性能呢?答案是肯定的,svelte(類似 vue),solid(類似 react) 就是這麼做的
Svelte,新興前端框架 Svelte 從入門到原理,Virtual DOM is pure overhead,虛擬DOM是純粹的浪費

Solidjs,SolidJS入門


對於 Svelte,尤雨溪​怎麼看

user avatar chongdianqishi Avatar leexiaohui1997 Avatar huajianketang Avatar xiaoxxuejishu Avatar guixiangyyds Avatar zhulongxu Avatar wmbuke Avatar weidewei Avatar kongsq Avatar tanggoahead Avatar youyoufei Avatar laggage Avatar
Favorites 29 users favorite the story!
Favorites

Add a new Comments

Some HTML is okay.