大家好,我是卡颂。

你可能看过上面这张图(或相似的图):

这是一张前端框架性能跑分表,表中每一行都是一个性能度量指标。

据我多年埋伏推特察看,采纳了细粒度更新技术的框架开发者广泛喜爱晒跑分表。

比方Solid.js作者Ryan Carniato写的这篇2020年JS框架性能比照内含15张跑分表

这些跑分表挂车尾的通常是ReactAngular12这样的业界出名框架。

不禁让人狐疑,前端提高这么快,React都这么拉跨啦?

本文会分享一些从跑分表中发现的乏味洞察。

虚构DOM到底慢不慢?

咱们先截取最后面两行,别离是页面加载后创立1000行表格所需工夫以及替换1000行列表所需工夫

从左到右性能顺次升高,其中第一列vanillajs原生JS,这也是泛滥框架毕生在追寻的指标。

能够看到,尽管React以及出名类React框架Preact排名倒数3、4,但同样作为类React框架的inferno排名却很靠前(第三名)。

这示意虚构DOM可能并不是性能瓶颈。

实时上,得益于多种虚构DOM的优化技巧,比方:

  • 数组两端比拟
  • 查找最小挪动次数

inferno虚构DOM可能是业界同类解决方案中最高效的。

这里简略介绍下两端比拟,假如diff前后的数据别离为:

// diff前abcd// diff后abfd

两端比拟会先排除数组雷同的前、后缀节点。例子中的雷同前缀是ab,雷同后缀是d

所以理论进行比照的是:

// diff前c// diff后f

简略、高效的优化策略。

因为ReactFiber架构应用链表实现,无奈进行两端比拟

细粒度更新yyds?

尽管虚构DOM能够被优化的很高效,但他毕竟为运行时带来不少的运算量。

在上表有一行指标,红色特地多(代表性能低),这行度量的是点击列表某一行使其高亮所需工夫:

这行的跑分后果:SolidJS > Svelte > Vue3.2 > inferno > ... > React > Angular

可见,采纳虚构DOM的框架性能广泛偏差。排名前3的框架技术架构为:

  • SolidJS:预编译 + 细粒度更新
  • Svelte:预编译 + 细粒度更新
  • Vue3:预编译 + 细粒度更新 + 虚构DOM

这是因为点击列表某一行使其高亮所需工夫度量的是部分的小扭转

这种类型扭转是基于订阅公布细粒度更新最善于的场景。

绝对的,也是虚构DOM最不善于的中央。

React有这么不堪么?

那么基于细粒度更新的框架有什么毛病,React又有什么性能长处呢?

答案是:继续的可交互工夫(consistently interactive)。

他度量的是:CPU和网络的闲暇工夫,即Chrome DevToolslighthouse工具中的TimeToConsistentlyInteractive指标。

图中右边绿字Short Tasks指向的都是耗时很短的JS工作,短耗时意味着浏览器有更多闲暇工夫重排、重绘,更不易卡顿。

与其绝对的是左边红字Long Tasks,指向的都是耗时很长的JS工作,此时浏览器更容易卡顿。

细粒度更新框架初始时会有为节点建设响应式更新的过程,比方:

  • Vue2中通过settergetter
  • Vue3中通过proxy

这一过程会有肯定CPU及内存开销(尽管随着proxy的遍及,JS原生反对响应式更新后,这部分开销会越来越低)。

React没有这部分开销,同时借由基于虚构DOM工夫切片React能进一步升高继续的可交互工夫

乏味的是,以上性能跑分表来源于开源我的项目js-framework-benchmark,该我的项目是有consistently interactive这一度量的。

然而有些基于细粒度更新的框架并没有抉择在跑分表中退出这一项的比照。

总结

能够看到,不同的技术有不同劣势:

  • 细粒度更新对于部分更新性能更佳
  • 基于虚构DOM工夫切片继续的可交互工夫性能更佳

当大家在聊性能时,最好先明确聊的是哪个指标,否则差别可能很大。