V8 终于发布了 v8.0

1,480 阅读4分钟

作者:Leszek Swirski

翻译:疯狂的技术宅

原文:v8.dev/blog/v8-rel…

未经允许严禁转载

终于来了。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%的内存

指针压缩平均可节省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.applyReflect.apply 和许多更高阶的数组内置函数(例如 Array.prototype.map)。

JavaScript

可选链

在编写属性访问链时,程序员经常要检查中间值是否为空(即 nullundefined )。没有错误检查的链可能会抛出错误,而带有显式错误检查的链很冗长,并且会产生有害的后果,即需要检查所有真实值而不是仅检查非空值。

// 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 的值为空(nullundefined)时,评估结果为 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 频道,然后很快尝试新功能。

欢迎关注前端公众号:前端先锋,免费领取前端工程化实用工具包。