大家好,我是卡颂。
你可能看过上面这张图(或相似的图):
这是一张前端框架性能跑分表,表中每一行都是一个性能度量指标。
据我多年埋伏推特察看,采纳了 细粒度更新 技术的框架开发者广泛喜爱晒跑分表。
比方
Solid.js
作者Ryan Carniato
写的这篇 2020 年 JS 框架性能比照内含 15 张跑分表
这些跑分表挂车尾的通常是 React
、Angular12
这样的业界出名框架。
不禁让人狐疑,前端提高这么快,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
简略、高效的优化策略。
因为
React
的Fiber
架构应用链表实现,无奈进行两端比拟
细粒度更新 yyds?
尽管 虚构 DOM能够被优化的很高效,但他毕竟为 运行时 带来不少的运算量。
在上表有一行指标,红色特地多(代表性能低),这行度量的是 点击列表某一行使其高亮所需工夫:
这行的跑分后果:SolidJS > Svelte > Vue3.2 > inferno > … > React > Angular
可见,采纳 虚构 DOM的框架性能广泛偏差。排名前 3 的框架技术架构为:
- SolidJS:预编译 + 细粒度更新
- Svelte:预编译 + 细粒度更新
- Vue3:预编译 + 细粒度更新 + 虚构 DOM
这是因为 点击列表某一行使其高亮所需工夫 度量的是 部分的小扭转。
这种类型扭转是基于 订阅公布 的细粒度更新 最善于的场景。
绝对的,也是 虚构 DOM最不善于的中央。
React 有这么不堪么?
那么基于 细粒度更新 的框架有什么毛病,React
又有什么性能长处呢?
答案是:继续的可交互工夫(consistently interactive)。
他度量的是:CPU
和网络的闲暇工夫,即 Chrome DevTools
的lighthouse
工具中的 TimeToConsistentlyInteractive
指标。
图中右边绿字 Short Tasks
指向的都是耗时很短的 JS
工作,短耗时意味着浏览器有更多闲暇工夫重排、重绘,更不易卡顿。
与其绝对的是左边红字 Long Tasks
,指向的都是耗时很长的JS
工作,此时浏览器更容易卡顿。
细粒度更新 框架初始时会有为节点建设 响应式更新 的过程,比方:
Vue2
中通过setter
、getter
Vue3
中通过proxy
这一过程会有肯定 CPU
及内存开销(尽管随着 proxy
的遍及,JS
原生反对 响应式更新 后,这部分开销会越来越低)。
React
没有这部分开销,同时借由基于 虚构 DOM的 工夫切片 ,React
能进一步升高 继续的可交互工夫。
乏味的是,以上性能跑分表来源于开源我的项目 js-framework-benchmark,该我的项目是有 consistently interactive
这一度量的。
然而有些基于 细粒度更新 的框架并没有抉择在跑分表中退出这一项的比照。
总结
能够看到,不同的技术有不同劣势:
- 细粒度更新 对于部分更新性能更佳
- 基于 虚构 DOM的 工夫切片 对继续的可交互工夫 性能更佳
当大家在聊性能时,最好先明确聊的是哪个指标,否则差别可能很大。