原文:https://v8.dev/blog/v8-release-76
译者:柴树杉(https://github.com/chai2010)
每隔六周,V8将会创建一个新的发布分支。每个Chrome Beta里程碑之前的版本都是从V8的Git仓库master分支出来的。最近我们开了V8的v7.6分支,它将在未来的几周内和Chrome 76的stable版本正式发布前处于协同测试阶段。V8的v7.6版本为码农们带来了诸多友好的特性。
性能改进(大小和速度)
`JSON.parse`改进
在现代的JS应用中,通常使用JSON格式传输数据。如果能够加速JSON的解析,那么也可以加快通信的相应。在新版本中,JSON解析器有了重大提速,这使得一些主流页面提供的JSON数据提高了2.7倍。
该图展示了JSON.parse
在各大流行网站的性能提升。在V8 v7.5之前,JSON是采用递归解析,这导致解析器的堆栈深度和JSON嵌套深度存在相关性。而V8 v7.6改用非递归的迭代式解析,通过管理自己定制的栈,这可以可以降低内存的使用(从而提高性能)。
新的JSON解析内存使用也更加高效。在创建最终结果对象前,通过缓存对象属性数据可以优化内存的分配。对于有明确属性的输入数据,预先为命名属性分配空间(最多128个命名属性)。如果JSON对象保护所以属性名字,我们则预先分配一个备用缓存空间(可能是数组或字典)。JSON数组现在倍解析为符合输入数据中元素数量的数组。
Frozen/sealed数组的改进
对于Frozen/sealed数组(包括有着数组行为的对象),性能具有较大改进。V8 v7.6优化了以下JS代码的模式,其中frozen是Frozen/sealed数组。
frozen.indexOf(v)
frozen.includes(v)
类似
fn(…frozen)
的传播使用嵌套数组传播调用
fn(…[…frozen])
apply方式调用
fn.apply(this, […frozen])
下图显示了这些改进:
更多细节请参考(fast frozen & sealed elements in V8):https://bit.ly/fast-frozen-sealed-elements-in-v8
Unicode字符串
优化字符串到Unicode的转换,大幅提高了String#localeCompare
、String#normalize
和Intl
等函数的性能。例如,对于单子节的字符串,String#localeCompare
将速度提升了2倍。
JavaScript语言特性
`Promise.allSettled`
当全部的Promise被设置后,Promise.allSettled
提供一个信号,不管是成功或者失败。如果我们不关心最终的成功与否的状态,只是想知道合适完成了工作就比较方便。具体的例子可以看这里:https://v8.dev/features/promise-combinators
改进BigInt支持
BigInt在语言中已经有更好的API支持了。可以通过BigInt的toLocaleString方法,根据区域进行格式化。和普通数值一样使用:
12345678901234567890n.toLocaleString('en'); // ????
// → '12,345,678,901,234,567,890'
12345678901234567890n.toLocaleString('de'); // ????
// → '12.345.678.901.234.567.890'
如果希望用同样的区域格式化多个BigInt数字,可以使用Intl.NumberFormat
,它支持format
和formatToParts
方法。这样可以用一个格式化器格式化多个数字:
const nf = new Intl.NumberFormat('fr');
nf.format(12345678901234567890n); // ????
// → '12 345 678 901 234 567 890'
nf.formatToParts(123456n); // ????
// → [
// → { type: 'integer', value: '123' },
// → { type: 'group', value: ' ' },
// → { type: 'integer', value: '456' }
// → ]
`Intl.DateTimeFormat`改进
程序中经常需要显示时间段。比如订酒店订时候,需要跟进入驻时长进行计费。而Intl.DateTimeFormat
提供了formatRange
和formatRangeToParts
方法,用于格式化时间段:
const start = new Date('2019-05-07T09:20:00');
// → 'May 7, 2019'
const end = new Date('2019-05-09T16:00:00');
// → 'May 9, 2019'
const fmt = new Intl.DateTimeFormat('en', {
year: 'numeric',
month: 'long',
day: 'numeric',
});
const output = fmt.formatRange(start, end);
// → 'May 7 – 9, 2019'
const parts = fmt.formatRangeToParts(start, end);
// → [
// → { 'type': 'month', 'value': 'May', 'source': 'shared' },
// → { 'type': 'literal', 'value': ' ', 'source': 'shared' },
// → { 'type': 'day', 'value': '7', 'source': 'startRange' },
// → { 'type': 'literal', 'value': ' – ', 'source': 'shared' },
// → { 'type': 'day', 'value': '9', 'source': 'endRange' },
// → { 'type': 'literal', 'value': ', ', 'source': 'shared' },
// → { 'type': 'year', 'value': '2019', 'source': 'shared' },
// → ]
此外,formatRange
和formatRangeToParts
方法还新支持timeStyle
和dateStyle
选项:
const dtf = new Intl.DateTimeFormat('de', {
timeStyle: 'medium',
dateStyle: 'short'
});
dtf.format(Date.now());
// → '19.06.19, 13:33:37'
本地栈遍历
V8可以遍历它的栈(调试或性能分析的时候),但是Windows-x64系统下无法遍历TurboFan生成的代码。这会导致本季调试器或ETW采样会破坏堆栈。最新的V8可以通过注册必要的元谁,改进Windows-x64系统的栈遍历支持。而且在v7.6版本中已经默认启用了该特性。
V8 API
git log branch-heads/7.5..branch-heads/7.6 include/v8.h
命令可以获取变更列表。而Chrome Beta可以从这里下载:https://www.google.com/chrome/beta/