作者:Leszek Swirski
翻译:疯狂的技术宅
未经允许严禁转载
终于来了。V8 每六个星期发布一个版本,每当我们发布一个版本时,就会出现有关当 V8 到版本 8 时会发生什么的问题。举行一个派对?我们会提供一个新的编译器吗?我们是否会跳过版本 8 和 9,而使 V8 停留在永恒的某个版本 X 中?经过超过 10 年的工作,在我们的第 100 篇博客文章中,很高兴地宣布我们的最新分支 V8 version 8.0 V8 发布了,我们终于可以回答这个问题:
它修复了错误并改进了性能。
我们将在几周内与 Chrome 80 Stable 协作,对该版本预期的一些要点进行预览。
性能
指针压缩
我们将所有的 void *
更改为 pv
,从而将源文件的大小减少了66%。
在 V8 堆中包含了一整套项目,例如浮点值,字符串,编译的代码和各种标记值(代表指向 V8 堆的指针或者小整数)。我们通过检查堆,发现这些标记的值占据了堆的很大部分!
标记值与系统指针的数据大小一样:对于 32 位体系结构,它们的宽度为 32 位,而在 64 位体系结构中,则为 64 位。在将 32 位版本与 64 位版本进行比较时,我们发现为 64 位版本每个标记值使用的堆内存是32 位版本的两倍。
幸运的是,我们有一个绝招。高位可以由低位合成。然后只需要将唯一的低位存储到堆中,这样就能节省宝贵的内存资源……大约能节省平均 40% 的堆内存!
指针压缩平均可节省40%的内存
在对内存进行改善时,通常会为性能为代价。但是我们很自豪地宣布,在 V8 及其垃圾收集器中,我们看到了真实网站性能的提高!
表格需要截图 v8.dev/blog/v8-rel…
如果指针压缩激起了你的兴趣,请随时关注我们的博客文章。
优化高阶内置
最近,我们消除了 TurboFan 优化管道中的限制,该限制阻止了对高阶内置程序进行积极的优化。
const charCodeAt = Function.prototype.call.bind(String.prototype.charCodeAt);
charCodeAt(string, 8);
到目前为止,对 TurboCan 来说,对 charCodeAt 的调用是完全不透明的,这导致了对用户定义函数的通用调用的产生。有了这一改变,现在可以识别出我们是在调用内置的 String.prototype.charCodeAt
函数,从而能够触发 TurboFan 中的进一步优化来改善对内置函数的调用,从而得到具有与以下代码相同的性能:
string.charCodeAt(8);
这种更改会影响其他一系列内置函数,例如 Function.prototype.apply
、Reflect.apply
和许多更高阶的数组内置函数(例如 Array.prototype.map
)。
JavaScript
可选链
在编写属性访问链时,程序员经常要检查中间值是否为空(即 null
或 undefined
)。没有错误检查的链可能会抛出错误,而带有显式错误检查的链很冗长,并且会产生有害的后果,即需要检查所有真实值而不是仅检查非空值。
// Error prone-version, could throw.
const nameLength = db.user.name.length;
// Less error-prone, but harder to read.
let nameLength;
if (db && db.user && db.user.name)
nameLength = db.user.name.length;
可选链(?.
)使程序员可以编写更强大的属性访问链,以检查中间值是否为空。如果中间值是空值,则整个表达式的计算结果为undefined
。
// Still checks for errors and is much more readable.
const nameLength = db?.user?.name?.length;
除了静态属性访问之外,还支持动态属性访问和调用。有关详细信息和更多示例,请参见我们的功能说明。
Nullish 合并
nullish合并运算符 ??
是新的用于处理默认值短路的二元运算符。当前有时会使用逻辑 ||
运算符来处理默认值,例如:
function Component(props) {
const enable = props.enabled || true;
// …
}
不建议用 ||
计算默认值,因为在 a||b
中,当 a
为假时,会被评估为 b
。如果将 props.enabled
显式设置为 false
,则 enable
仍然为 true
。
使用 nullish 合并运算符,在a ?? b
中,当 a
的值为空(null
或 undefined
)时,评估结果为 b
,否则为 a
。这是理想的默认值行为,用 ??
重写上面的例子可修复这个错误。
function Component(props) {
const enable = props.enabled ?? true;
// …
}
nullish 合并运算符和可选链是辅助功能,能很好地协同工作。可以进一步修改该示例,以处理未传递 props
自变量的情况。
function Component(props) {
const enable = props?.enabled ?? true;
// …
}
有关详细信息和更多示例,请参见我们的功能说明。
V8 API
请使用 git log branch-heads/7.9..branch-heads/8.0 include/v8.h
获取 API 更改列表。
具有Active V8 checkout 权限的开发人员可以用 git checkout -b 8.0 -t branch-heads/8.0
来尝试使用 V8 v8.0 中的新功能。另外,你可以订阅 Chrome 的 Beta 频道,然后很快尝试新功能。