JavaScript引擎V8发布8.0版本:性能大改进
JavaScript引擎V8发布了8.0版本,此版本除了修复一些bug,毫无疑问又带来了性能的提高。目前是预览,正式版将于几个星期后随Chrome80Stable一起发布。
性能改进
先看看性能改进,这包括内存占用减少与速度提升:
指针压缩
V8堆包含整个项目所有东西,例如浮点值、字符串字符、编译的代码和标定值(taggedvalues),标定值代表指向V8堆的指针或小整型,开发团队发现这些标记值占据了堆的大部分空间。
标定值与系统指针一样大,对于32位架构来说,它们的宽度为32位,而在64位架构中,则为64位。在将32位版本与64位版本进行比较时,为每个标记值使用的堆内存是原来的两倍。
此版本通过一个方法减小了这一块内存:指针压缩。因为高位可以由低位合成,只需要将唯一的低位存储到堆中即可节省内存资源,经过测试,平均节省了40%的堆内存。
通常在减少内存的同时,也会牺牲速度性能,但是经过这一改进,V8及其垃圾收集器中,都能够看到真实网站性能的提升。
优化高阶内置程序
此版本消除了TurboFan优化管道中的一个限制,该限制阻止了对高阶内置函数的优化。
constcharCodeAt=Function.prototype.call.bind(String.prototype.charCodeAt);charCodeAt(string,8);
charCodeAt对TurboFan的调用是完全不透明的,从而导致生成对用户定义函数的通用调用。通过此更改,现在可以识别出实际上是在调用内置String.prototype.charCodeAt函数,从而能够触发TurboFan库存中所有的进一步优化来改善对内置函数的调用,进而获得与以下代码相同的性能:
string.charCodeAt(8);
JavaScript
特性方面也有所变化,带来了两个新特性:
OptionalChaining
在编写属性访问链时,开发者经常需要检查中间值是否为空(null或undefined),这样可能会写出很冗长的显式错误检查链。
//Errorprone-version,couldthrow.constnameLength=db.user.name.length;//Lesserror-prone,buthardertoread.letnameLength;if(db&&db.user&&db.user.name)nameLength=db.user.name.length;
OptionalChaining(?.)使开发者可以编写更可靠的属性访问链,以检查中间值是否为空。如果中间值是空值,则整个表达式的计算结果为undefined。
//Stillchecksforerrorsandismuchmorereadable.constnameLength=db?.user?.name?.length;
同时,除了静态属性访问之外,OptionalChaining还支持动态属性访问和调用。
null合并(NullishCoalescing)
另一个与OptionalChaining很接近的特性是null判断合并(NullishCoalescing),由特定的NullishCoalescing操作符??启用,它是一个新的短路二元运算符。
现在有时会使用逻辑||运算符处理默认值,例如:
functionComponent(props){constenable=props.enabled||true;//…}
运算a||b,当a为非真时结果为b,如果props.enabled本身显式设置为“false”,那么这样的运算还是会得到第二个运算数“true”,也就是enable=true。
现在使用null合并运算符??,当a为空,也就是null或者undefined时,a??b的运算结果为b,否则为a,这样的默认值处理行为才是符合逻辑的,弥补了前边讲到的问题。
functionComponent(props){constenable=props.enabled??true;//…}
同时,null合并运算符和OptionalChaining是辅助功能,可以很好地协同工作。它们可以进一步处理上述示例中没有任何props参数传入的情况。
functionComponent(props){constenable=props?.enabled??true;//…}
此外,API有一些变化,可以通过以下方式查看:
gitlogbranch-heads/7.9..branch-heads/8.0include/v8.h
更新说明:
https://v8.dev/blog/v8-release-80