1
头图

先说结论

  • 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 渲染 divv-for 渲染函数式组件v-for 渲染普通组件
一万div复用key渲染耗时-61ms/6.1us85ms/8.5us122ms/12.2us
一万div不复用key渲染耗时26ms/2.6us91ms/9.1us82ms/8.2us360ms/36us
十万div复用key渲染耗时-286ms/2.9us392ms/3.9ms918ms/9.2us
十万div不复用key渲染耗时265ms/2.7us499m/5us505ms/5us13881ms/138.8us
十万div内存占用528mb/5.4kb586mb/6kb652mb/6.7kb907mb/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是纯粹的浪费

SolidjsSolidJS入门


对于 Svelte,尤雨溪​怎么看


momo707577045
2.4k 声望603 粉丝

[链接]