大家好,我是
ssh
。
太长不看版:
在 JavaScript 框架竞争中,Vue.js 团队宣布其响应式系统将成为最快的。通过引入 alien-signals 库,Vue 3.5 实现了显著的性能提升,特别是在内存使用和计算效率方面。新的实现降低了内存使用量,提升了性能,并优化了代码抽象,使得 Vue 在各种性能测试中表现出色。
学习要点
-
Vue.js 性能提升
:Vue 3.5 引入
alien-signals
库,显著提升了响应式系统的性能。
-
内存优化
:内存使用量减少约 13%,从 2.3MB 降低到 2.0MB。
-
性能测试结果
:在多种性能测试中,Vue 3.5 表现优异,性能提升超过 30 倍。
-
代码抽象改进
:新的实现消除了与外部实现的耦合,使代码更简洁和易于维护。
-
具体优化措施
:包括移除命名空间使用,提升模块根级导出的性能。
-
Alien Signals 细节
:
alien-signals
库通过严格的约束条件实现卓越性能,整体性能约为 Vue 3.4 的 400%。
-
示例代码
:提供了基本用法和 effect 作用域的示例,展示了
alien-signals
的实际应用。
-
对比分析
:JS Reactivity Benchmark 显示
alien-signals
在性能上领先其他响应式框架。
以后的文章我都会加入这个部分,基于 AI 总结,方便没空了解细节的同学快速阅读。
正文如下:
在 JavaScript 框架竞争激烈的今天,提高性能始终是各大框架追逐的目标。最近,Vue.js 团队在 X 上高调宣布,Vue 的响应式将成为所有框架中最快的。
并附上了一个重要的 GitHub PR 链接:升级PR。
https://github.com/vuejs/core/pull/12349
这个 PR 的核心是引入了
alien-signals
,一个基于 Vue 3.4 响应式系统重新编写的
signals
库,旨在确保响应式系统的高性能实现,目前,这是所有
signals
库中最快的实现。
在我之前的文章里,详细介绍过 Signals 的标准化提案,感兴趣可以回顾一下:
主要优化点
-
在创建大量
ref
、
computed
和
effect
实例时,内存使用减少了约 13%(从 2.3MB 降低到 2.0MB)。
-
各种性能测试结果更优,尤其是在更改
ref
后读取大量
computed
的场景。Vue 3.5 在这种情况下存在显著的性能缺陷,而当前实现解决了这个问题,性能提升超过 30 倍(随规模增加而提升)。
-
以前的调度逻辑与外部实现存在耦合(如
Dep
清理、调试事件、递归处理);新的实现消除了这些耦合,使代码更简洁和易于维护。
性能提升对比
以下是基准测试的结果:
name hz min max mean p75 p99 p995 p999 rme samples
· create computed 6,111,709.97 0.0000 0.3307 0.0002 0.0002 0.0002 0.0002 0.0003 ±0.53% 3055856 [1.28x] ⇑
create computed 4,790,560.55 0.0001 2.8602 0.0002 0.0002 0.0003 0.0003 0.0005 ±1.19% 2395281 (baseline)
· write ref, don't read computed (without effect) 3,725,946.87 0.0002 0.1777 0.0003 0.0003 0.0003 0.0003 0.0004 ±0.16% 1862974 [1.19x] ⇑
write ref, don't read computed (without effect) 3,138,437.74 0.0002 1.4873 0.0003 0.0003 0.0004 0.0004 0.0005 ±1.21% 1569219 (baseline)
· write ref, don't read computed (with effect) 1,629,737.97 0.0005 0.1867 0.0006 0.0006 0.0007 0.0007 0.0008 ±0.11% 814869 [1.20x] ⇑
write ref, don't read computed (with effect) 1,362,345.64 0.0006 0.1455 0.0007 0.0008 0.0008 0.0008 0.0010 ±0.13% 681173 (baseline)
· write ref, read computed (without effect) 1,961,824.76 0.0004 0.1808 0.0005 0.0005 0.0005 0.0006 0.0007 ±0.12% 980913 [1.06x] ⇑
write ref, read computed (without effect) 1,848,260.85 0.0004 0.1488 0.0005 0.0005 0.0006 0.0006 0.0007 ±0.13% 924131 (baseline)
· write ref, read computed (with effect) 1,475,801.43 0.0005 0.2211 0.0007 0.0007 0.0008 0.0008 0.0010 ±0.12% 737901 [1.14x] ⇑
write ref, read computed (with effect) 1,296,434.21 0.0007 0.2508 0.0008 0.0008 0.0008 0.0009 0.0011 ±0.16% 648218 (baseline)
· write ref, don't read 1000 computeds (without effect) 3,300,382.44 0.0002 0.1930 0.0003 0.0003 0.0003 0.0004 0.0004 ±0.14% 1650192 [1.03x] ⇑
write ref, don't read 1000 computeds (without effect) 3,189,502.88 0.0002 0.1763 0.0003 0.0003 0.0003 0.0004 0.0005 ±0.14% 1594752 (baseline)
· write ref, don't read 1000 computeds (with multiple effects) 3,222.67 0.3063 0.5532 0.3103 0.3108 0.3488 0.3917 0.5250 ±0.19% 1612 [1.38x] ⇑
write ref, don't read 1000 computeds (with multiple effects) 2,329.65 0.4206 0.6286 0.4292 0.4292 0.4997 0.5215 0.5671 ±0.19% 1165 (baseline)
· write ref, don't read 1000 computeds (with single effect) 3,734.95 0.2648 0.3821 0.2677 0.2683 0.2855 0.2986 0.3510 ±0.09% 1868 [1.71x] ⇑
write ref, don't read 1000 computeds (with single effect) 2,186.19 0.4434 0.6528 0.4574 0.4565 0.5061 0.5221 0.5846 ±0.16% 1094 (baseline)
· write ref, read 1000 computeds (no effect) 4,694.97 0.2105 0.3849 0.2130 0.2142 0.2301 0.2382 0.3271 ±0.12% 2348 [1.26x] ⇑
write ref, read 1000 computeds (no effect) 3,718.71 0.2292 9.4632 0.2689 0.2329 1.0790 2.5163 6.3315 ±5.98% 1860 (baseline)
· write ref, read 1000 computeds (with multiple effects) 2,845.64 0.3453 0.6213 0.3514 0.3512 0.4014 0.4358 0.5546 ±0.21% 1423 [1.33x] ⇑
write ref, read 1000 computeds (with multiple effects) 2,142.70 0.4569 0.7351 0.4667 0.4664 0.5183 0.5565 0.6951 ±0.22% 1072 (baseline)
· write ref, read 1000 computeds (with single effect) 2,265.62 0.4338 0.9382 0.4414 0.4392 0.5991 0.6087 0.6304 ±0.36% 1133 [1.48x] ⇑
write ref, read 1000 computeds (with single effect) 1,529.78 0.6415 0.8937 0.6537 0.6526 0.7195 0.7378 0.8937 ±0.18% 765 (baseline)
· 1000 refs, read 1 computed (without effect) 19,686.23 0.0490 0.1665 0.0508 0.0495 0.0595 0.0631 0.0935 ±0.16% 9844 [3.41x] ⇑
1000 refs, read 1 computed (without effect) 5,775.97 0.1611 0.3445 0.1731 0.1746 0.2057 0.2170 0.2689 ±0.18% 2888 (baseline)
· 1000 refs, read 1 computed (with effect) 22,764.26 0.0427 0.1713 0.0439 0.0430 0.0534 0.0585 0.0983 ±0.16% 11383 [3.63x] ⇑
1000 refs, read 1 computed (with effect) 6,268.22 0.1492 0.3157 0.1595 0.1620 0.1907 0.2024 0.2408 ±0.18% 3135 (baseline)
-
-
新版本:每秒 6,111,709.97 次,[1.28x] 提升
-
-
修改
ref
,不读取
computed
(无
effect
)
-
新版本:每秒 3,725,946.87 次,[1.19x] 提升
-
-
修改
ref
,读取 1000 个
computed
-
无
effect
场景下,新版本提升 1.26 倍
-
多
effect
场景下,新版本提升 1.33 倍
详细的基准测试请参考 GitHub PR 链接中的表格(https://github.com/vuejs/core/pull/12349)。
随后,尤大也补充了一个 commit,移除命名空间的使用:
-
原因
:之前使用命名空间是因为在基准测试中表现出更好的性能,但发现这是由于 Vitest 基准测试目前的模块评估方式造成的。跨模块导入绑定的每次访问都有开销,从而影响了性能。
-
解决方案
:将模块根级导出提升到本地常量中,以此来代替命名空间访问。这种方法不仅可以提升性能,还更适合代码压缩器,并能减少捆绑包的大小。
-
结果
:使用捆绑反应模块进行基准测试后,发现删除命名空间方式后性能略有提升,对比 571ba05 之前和之后的结果,整体改进显著。
体积报告
此次优化对包大小的影响:
文件
|
大小变化
|
Gzip 变化
|
Brotli 变化
|
runtime-dom.global.prod.js
|
+1.11 kB
|
+121 B
|
+98 B
|
vue.global.prod.js
|
+1.11 kB
|
+114 B
|
+71 B
|
Alien Signals 项目细节
项目简介
alien-signals
是一个轻量级的信号库,由 StackBlitz 推出,目标是创建一个具有最低开销的 signal 库。
Github 地址:https://github.com/stackblitz/alien-signals
这个库旨在通过一些限制条件来实现卓越的性能: