当前端框架聊性能,聊的是同一个性能么?

SegmentFault

共 1814字,需浏览 4分钟

 ·

2021-08-30 09:39

作者:卡颂
来源:SegmentFault 思否社区

大家好,我是卡颂。
你可能看过下面这张图(或类似的图):

这是一张前端框架性能跑分表,表中每一行都是一个性能度量指标。
据我多年潜伏推特观察,采用了细粒度更新技术的框架开发者普遍喜欢晒跑分表。
比如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能进一步降低持续的可交互时间

总结

可以看到,不同的技术有不同优势:
  • 细粒度更新对于局部更新性能更佳

  • 基于虚拟DOM时间切片持续的可交互时间性能更佳


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


点击左下角阅读原文,到 SegmentFault 思否社区 和文章作者展开更多互动和交流,扫描下方”二维码“或在“公众号后台回复“ 入群 ”即可加入我们的技术交流群,收获更多的技术文章~

- END -


浏览 20
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报