46

【Node.js丨主题周】Chrome V8 与 Node.js

 5 years ago
source link: http://www.10tiao.com/html/205/201806/2651089336/1.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

小编说:从某种意义上来说,Node.js 并不是一个从零开始编写的 JavaScript 运行时,它其实也是站在“巨人的肩膀”上进行了一系列的拼凑和封装得到的结果。它的高效离不开一些很牛的第三方程序和类库。比如本文我们介绍的Chrome V8。

本文选自《Node.js:来一打 C++ 扩展》,了解本书详情点击阅读原文

Chrome V8 简称 V8,是由谷歌开源的一个高性能 JavaScript 引擎。该引擎采用 C++ 编写,Google Chrome 浏览器用的就是这个引擎。V8 可以单独运行,也可以嵌入 C++ 应用当中。

和其他的 JavaScript 引擎一样,V8 会编译、执行 JavaScript 代码,并一样会管理内存、垃圾回收等。

就是因为 V8 的高性能以及跨平台等特性,所以它也是 Node.js 的 JavaScript 引擎。

  • 高效

V8 开发小组由一群程序语言专家组成。其中核心工程师 Lars Bak 之前在 Sun 公司工作,专注于 Java 虚拟机加速技术的研究,产出了 HotSpot,除此之外,他还曾开发了 Strongtalk1。

所以,V8 的代码里面蕴含了从 HotSpot 和 Strongtalk 中汲取的精髓。

该研发小组从 2006 年开始研发 V8,原因是当年市面上的各种 JavaScript 引擎效率都比较低下。在 Lars Bak 等人的贡献下,JavaScript 引擎添加了新的一员—— Chrome V8,并且效率非常高。

V8 的高效主要体现在以下 4 个特性上面。

(1) JIT 编译

JIT 编译,全称 Just-In-Time 编译,也就是即时编译。它编译出的结果直接是机器语言,而不是字节码。这样大大提高了 V8 在执行 JavaScript 时的效率。不过后来其他的几家 JavaScript引擎也渐渐推出了对 JIT 的支持。

(2) 垃圾回收

这个特性在 Java 领域中使用得比较多。虽然其他语言或者其他的 JavaScript 引擎实现都有垃圾回收,但是 V8 的垃圾回收借鉴了 Java VM 的精确垃圾回收管理,而其他很多语言的垃圾回收用的是保守垃圾管理。

相较而言,V8 的这套垃圾回收机制的效率要远远高于其他一些垃圾回收机制实现——实际上代价就是这种机制的实现难度更大。

(3) 内联缓存(Inline Cache)

V8 使用了内联缓存的特性来提高属性的访问效率。如有一个访问是 this. 蛋花汤,没有内联缓存的时候,每次要取蛋花汤的话都会对哈希表进行一次寻址,而加入了内联缓存的特性之后,V8 能马上知道这个属性的一个偏移量,而不用再次计算寻址的偏移量了。

(4) 隐藏类

由于 JavaScript 是一门动态的编程语言,因此哪怕是在 ES6 及以上版本的规范中有了class 的一个定义,开发者也能非常方便地对一个对象添加或者移除一个属性。

隐藏类就是对这样一套对象体系中的一个黑科技的包装——所有如属性一样的对象会被归为同一个隐藏类。

下面举个简单的例子:

一开始根据 Pet 创建了 蛋花汤 这个对象。在最开始初始化的时候 V8 就会创建一个隐藏类(假设是 P0),这是一个空类,因为它还没有任何的属性;后来 this.type = type 执行了,隐藏类就有了 type 属性,这个时候就又多了一个 P1 的隐藏类——P1 是基于 P0 创建的,并且多了 type 属性;接着,name 被赋值上去,于是隐藏类又多了一个 P2。

然后在创建 南瓜饼 对象的时候,又走了上面的老路,只不过这次不是创建隐藏类 P0、P1和 P2 了,而是直接沿用它们。在初始化 南瓜饼 的时候,它依次会属于上面创建的3 个隐藏类,直到最后它跟 蛋花汤 一样都属于 P2。

最后一行代码在给 蛋花汤 赋值 age 的时候,又一个新的隐藏类 P3 会被创建。这个时候 蛋花汤 和 南瓜饼 分别属于 P3 和 P2。这些描述分别如下图。

最开始的蛋花汤和南瓜饼隐藏类归属

赋值 type 后的蛋花汤和南瓜饼隐藏类归属

赋值 name 后的蛋花汤和南瓜饼隐藏类归属

最终的蛋花汤和南瓜饼隐藏类归属

隐藏类和内联缓存这两把“匕首”联合起来,是 V8 高效的一个非常重要的原因,因为同一个隐藏类的对象们能用同一套内联缓存来寻址。

  • 遵循 ECMAScript

在当前 V8 的项目主页中,有一句话表明了它是遵循 ECMA-262 标准的:

“V8 implements ECMAScript as specified in ECMA-262.”

就目前来说 ECMA-262 标准(曾)发布了 7 个大版本。

Generator 函数的爱称,因其有一个显著的标识——形如菊花的星号(*)而得名。

V8 在开发的过程中也一直追着 ECMAScript 发布的脚步,如基本上完成了对 ES6 的支持,而且最新版也对 async/await 函数进行了支持。

也正是因为 V8 对 ECMAScript 标准紧追不舍,才有了 Node.js 能及时跟上 ECMAScript 最新语法的情况。如 Node.js 7.6 正式默认支持 async/await 功能就是沾了 V8 的光。

  • Node.js 与 Chrome V8

下面是 V8 与 Node.js 的部分版本对照表。

Node.js 一直紧跟 V8 的版本脚步在迭代。

Node.js 与 V8 实际上看起来更像是一对情侣,而不仅仅是 Node.js 一厢情愿地使用 V8 作为自己的底层支持。

在 Chrome V8 的博客中曾经有一篇文章名为《V8 ❤ Node.js》。Node.js 在几年发展中的流行度稳步增长,于是有了 V8 的“姑娘,你成功引起了我的注意”。现在 V8 也有一些工作是为 Node.js 而做的:

  • 在 Chrome 开发者工具中可以调试 Node.js;

  • 加速 ES6;

  • 针对 Node.js vm 模块和 REPL 的一些修复;

  • Async / await。

本文选自《Node.js:来一打 C++ 扩展》


 

博文视点

您阅读的专业智库

喜欢请分享至朋友圈

了解更多本书详情请点击阅读原文

长按二维码轻松关注


点击阅读原文,即可快速抵达本书详情页!


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK