猿学~Node.js背后的V8引擎优化技术

本文探讨了Node.js性能背后的关键因素——V8引擎的优化技术,包括隐藏类、内联缓存和两次编译与反优化。通过理解和遵循V8友好的编码实践,可以显著提升JavaScript代码的执行速度。文章提供了多个示例,揭示了如何避免隐藏类的改变、优化内联缓存使用以及减少Deoptimization,以实现更高效的内存管理和垃圾收集。
摘要由CSDN通过智能技术生成

 Node.js的执行速度远超Ruby、Python等脚本语言,这背后都是V8引擎的功劳。本文将介绍如何编写高性能Node.js代码。V8是Chrome背后的JavaScript引擎,因此本文的相关优化经验也适用于基于Chrome浏览器的JavaScript引擎。

 V8优化技术概述

  V8引擎在虚拟机与语言性能优化上做了很多工作。不过按照Lars Bak的说法,所有这些优化技术都不是他们创造的,只是在前人的基础上做的改进。

  隐藏类(Hidden Class)

  为了减少JavaScript中访问属性所花的时间,V8采用了和动态查找完全不同的技术实现属性的访问:动态地为对象创建隐藏类。这并不是什么新想法,基于原型的编程语言Self就用map来实现了类似功能。在V8中,当一个新的属性被添加到对象中时,对象所对应的隐藏类会随之改变。

  我们用一个简单的JavaScript函数来加以说明:

function Point(x, y) {
    this.x = x;
    this.y = y;
}

  当new Point(x, y)执行时,一个新的Point对象会被创建。如果这是Point对象第一次被创建,V8会为它初始化一个隐藏类,不妨称作C0。因为这个对象还没有定义任何属性,所以这个初始类是一个空类。到此时为止,对象Point的隐藏类是C0(如图1)。

图1 对象Point的隐藏类C0

  执行函数Point中的第一条语句会为对象Point创建一个新的属性x。此时,V8会在C0的基础上创建另一个隐藏类C1,并将属性x的信息添加到C1中:这个属性的值会被存储在距Point对象偏移量为0的地方(如图2)。

图2 对象Point的隐藏类被更新为C1

  在C0中添加适当的类转移信息,使得当有另外的以其为隐藏类的对象在添加了属性x之后能找到C1作为新的隐藏类。此时对象Point的隐藏类更新为C1。

  执行函数Point中的第二条语句会添加一个新的属性y到对象Point中。同理,此时V8会有以下操作。

  • 在C1的基础上创建另一个隐藏类C2,并在C2中添加关于属性y的信息:这个属性将被存储在内存中离Point对象的偏移量为1的地方。
  • 在C1中添加适当的类转移信息,使得当有另外的以其为隐藏类的对象在添加了属性y之后能找到C2作为新的隐藏类。此时对象Point的隐藏类被更新为C2(如图3)。

图3 对象Point的隐藏类被更新为C2

  乍一看似乎每次添加一个属性都创建一个新的隐藏类非常低效。实际上,利用类转移信息,隐藏类可以被重用。下次创建一个Point对象时,就可以直接共享由最初那个Point对象所创建出来的隐藏类。

  例如,又有一个Point对象被创建出来,一开始Point对象没有任何属性,它的隐藏类将会被设置为C0。当属性x被添加到对象中时,V8通过C0到C1的类转移信息将对象的隐藏类更新为C1,并直接将x的属性值写入到由C1所指定的位置(偏移量0)。当属性y被添加到对象中时,V8又通过C1到C2的类转移信息将对象的隐藏类更新为C2,并直接将y的属性值写入到由C2所指定的位置(偏移量1)。尽管JavaScript比通常的面向对象编程语言都更加动态一些,然而大部分JavaScript程序都会表现出像上文描述的那样运行时高度结构

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值