V8 JavaScript引擎研究(二)高性能探秘

V8的高性能探秘

V8项目负责人Lars Bak:V8的所有优化都不是原创的。V8组合了过往对于动态语言的各种优化技术,因而具有了非常高效的性能。

快速属性访问

JavaScript是动态编程语言,这意味着可以动态的增加或删除对象的属性。

以往实现

大多数的JavaScript引擎都是使用类似字典的数据结构来保存一个对象的属性,在这种结构下每次访问一个属性都需要动态查找其在内存中的位置。

  • 优势:

    实现简单。

  • 劣势:

    效率低。相对于Java、Smalltalk等语言,由于对象的class有着固定的布局,因此属性在内存中有着由编译器生成相对于对象的固定位移,因此访问属性要快得多,可能仅需要一条机器指令。

V8的实现

为了减少访问属性的耗时,V8没有使用动态动态查找来访问属性。

V8为每个对象创建了一个隐藏类(Hidden Class),每当增加一个属性时更换新的隐藏类。

举例说明:

1 function Point(x, y)
2 {
3   this.x = x;
4   this.y = y;
5 }

当调用 new Point(x, y) 时产生一个新的Point对象,V8这样来处理:首先创建一个Point的隐藏类,在此例中假设叫C0,此时对象没有任何属性,初始时类是空的。在此阶段,Point对象的隐藏类为C0。

当执行Point里的第一条语句 this.x = x; 创建Point对象的一个新属性x。这时V8创建另外一个基于C0的隐藏类C1,然后在C1中增加描述信息,指明Point对象拥有属性x,并存储在相对于Point对象的位移0处。同时更新C0的类转移信息,指明当基于C0隐藏类的对象增加了属性x时,此对象的隐藏类将由C0替换为C1。在此阶段,Point对象的隐藏类为C1。

当执行Point里的第一条语句 this.y = y; 创建Point对象的一个新属性y。这时V8创建另外一个基于C1的隐藏类C2,然后在C2中增加描述信息,指明Point对象也拥有属性y,并存储在相对于Point对象的位移1处。同时更新C1的类转移信息,指明当基于C1隐藏类的对象增加了属性y时,此对象的隐藏类将由C1替换为C2。在此阶段,Point对象的隐藏类为C2。

无论何时只要增加一个属性就创建一个隐藏类,这种做法似乎看上去非常低效,然而由于类的转移信息,隐藏类可以被重用。想象一下这样的场景,当下一次一个新的Point对象被创建后,就不再需要创建新的隐藏类,新的Point对象将共享为第一个Point对象所创建的一系列隐藏类,具体过程如下:

初始化一个没有任何属性的Point对象,此时初始的隐藏类C0适用于此对象。

当增加属性x后,V8遵循从C0到C1的类转移信息,然后在C1指定的位移处写入x的值。

当增加属性y后,V8遵循从C1到C2的类转移信息,然后在C2指定的位移处写入y的值。

虽然JavaScript比大多数面向对象的语言更加动态,但绝大多数JavaScript程序的运行时行为导致了高度使用上述方法的共享结构。

  • 优势:

    不需要使用动态查找字典来访问对象的属性,尤其是当创建大量相同的对象时效率大幅提升。

    可以让V8使用基于隐藏类的优化技术-内联缓存(Inline Caching)。

  • 劣势:

    实现略复杂。

    每次对象新增属性都需要创建一个新的隐藏类,极端情况下效率非常低。

内联缓存&动态机器码生成

V8的内联缓存依托于隐藏类技术,这里的内联与C++中的内联是两个不同的概念。

当第一次执行JavaScript代码时V8直接将其编译成机器码,而不产生中间的字节码。(*Google已经发布了新的JavaScript解释器Ignition,旨在减少内存消耗,在一些内存有限的设备上使用)

在第一次指定访问一个给定对象的属性的代码时,V8会确定此对象的隐藏类。V8预测未来在此代码段上执行的所有对象属性访问都拥有相同的隐藏类,并将属性访问的代码通过使用此隐藏类,打进使用内联缓存访问指令的补丁(通常即为一条对内存偏移地址的访问指令,也就是内联的概念)。如果V8预测命中,则大大优化了属性访问耗时;如果V8未命中,则将打进的补丁代码移除,重新创建隐藏类并访问属性。

这样在处理大量相同类型的对象并频繁创建和访问时(绝大多数JavaScript代码都是如此执行),效率将极大提升。

高效的垃圾回收实现

V8垃圾回收机制简介

V8在运行时自动回收不再需要使用的对象内存,也即是垃圾回收。

V8使用了全暂停式(stop-the-world)、分代式(generational)、精确(accurate)等组合的垃圾回收机制,来确保更快的对象内存分配、更短的垃圾回收时触发的暂停以及没有内存碎片。

V8的垃圾回收有如下几个特点:

  • 当处理一个垃圾回收周期时,暂停所有程序的执行。
  • 在大多数垃圾回收周期,每次仅处理部分堆中的对象,使暂停程序所带来的影响降至最低。
  • 准确知道在内存中所有的对象及指针,避免错误地把对象当成指针所带来的内存泄露。
时间: 2024-12-13 18:16:12

V8 JavaScript引擎研究(二)高性能探秘的相关文章

V8 JavaScript引擎研究(一)简介

V8 JavaScript引擎简介 V8是Google公司的高效JavaScript引擎.它使用C++开发,完全开源,最著名的是使用在Chrome浏览器中作为JavaScript解析引擎. V8实现了ECMAScript-262标准,可以运行在Windows(XP及以上).Mac OS X(10.5及以上)以及使用IA-32.x64或ARM处理器的Linux系统. V8通常使用在浏览器中作为JavaScript的解析引擎,也可以嵌入到任何应用程序中使用. 基于C++的应用程序通过V8可以暴露任何

V8 JavaScript引擎研究(三)垃圾回收器的实现

V8垃圾回收机制简介 V8垃圾回收器的实现,是V8高效的一个非常重要的原因. V8在运行时自动回收不再需要使用的对象内存,也即是垃圾回收. V8使用了全暂停式(stop-the-world).分代式(generational).精确(accurate)等组合的垃圾回收机制,来确保更快的对象内存分配.更短的垃圾回收时触发的暂停以及没有内存碎片. V8的垃圾回收有如下几个特点: 当处理一个垃圾回收周期时,暂停所有程序的执行. 在大多数垃圾回收周期,每次仅处理部分堆中的对象,使暂停程序所带来的影响降至

V8 javascript引擎初步体验

v8 引擎,不必多说,大名鼎鼎,迄今最快的js引擎. 这么好的东西,如果尽在浏览器中使用,太浪费了,也希望用到其他地方,比如一些客户端开发中. 闲言少讲,这就开始 下载源码 去官方网站:https://code.google.com/p/v8/ 我喜欢用git,所以从这里下载 git clone git://github.com/v8/v8.git v8 && cd v8 编译 我为android平台编译的,折腾了好久,记录一些重点.你首先要看这个:http://code.google.c

V8:V8(Javascript引擎)

ylbtech-V8:V8(Javascript引擎) Lars Bak是这个项目的组长,目前该JavaScript引擎已用于其它项目的开发.第一个版本随着第一个版本的Chrome于2008年9月2日发布. 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 1. https://baike.baidu.com/item/V8/6178125 2. 6.返回顶部 作者:ylbtech出处:http://ylbtech.cnblogs.com/本文版权归作者和博客园共有,欢迎转载

[C#]VS2017使用google v8 Javascript引擎

V8是JavaScript渲染引擎,号称是最快的,因为品牌效应,我信了,相关介绍网上一堆,我就不粘贴了,原库是直接提供给c++调用的,这里会用到微软的ClearScript.V8(包装v8),JavaScriptEngineSwitcher.V8(包装ClearScript)两个C#库. 一.安装: 1.项目右键,选择 管理NuGet程序包 2.搜索下面4个包并安装 3.检查引用目录下面是否存在相关dll链接库,不存在需要手动添加,运行后如果碰到缺少相关dll的问题,将项目根目录下package

windows下使用VS2015编译V8 JavaScript引擎(v5.5 - 2016/09)

今天心血来潮, 下载了 v8,,然后就想着用vs编译 但是大家都苦恼的是 v8并不直接提供 vs用的项目文件和解决方案(.sln) 于是,在网上搜来搜去, 折腾来折腾去的; 终于一点一点的尝试, 可以执行 python gypfiles\gyp_v8.py -Dtarget_arch=x64 但是网上搜到的都是 python build\gyp_v8.py -Dtarget_arch=x64 可我git clone 的没有build文件夹啊, 好歹根据 https://github.com/v8

缠缠绵绵的v8与c++ | 之二

Embedder's Guide(记得FQ) 如果你已经读过 Getting Started, 那么现在,你已经对V8的一些关键概念比较熟悉了.比如,V8是一个独立的虚拟机,V8的handle,scope和context的概念. 这篇文章更进一步讨论了这些概念,并且介绍了另外的一些将V8嵌入到C++中至关重要的概念. V8的API提供了这样一些功能,包括编译和执行脚本,访问C++中的方法和数据结构,处理错误以及开启安全检查.你的应用程序可以像使用其他一些C++库一样来使用V8,而只需要包含它的头

JavaScript 引擎 V8 执行流程概述

本文首发于 vivo互联网技术 微信公众号? 链接:https://mp.weixin.qq.com/s/t__Jqzg1rbTlsCHXKMwh6A 作者:赖勇高 本文主要讲解的是V8的技术,是V8的入门篇,主要目的是了解V8的内部机制,希望对前端,快应用,浏览器,以及nodejs同学有些帮助.这里不涉及到如何编写优秀的前端,只是对JS内部引擎技术的讲解. 一.V8来源 V8的名字来源于汽车的"V型8缸发动机"(V8发动机).V8发动机主要是美国发展起来,因为马力十足而广为人知.V8

JavaScript 引擎「V8」发布 8.0 版本,内存占用量大幅下降

上周,JavaScript 引擎「V8」的开发团队在该项目官方网站上正式宣布推出最新的 8.0 版本.这次更新的重点主要集中在错误修复及性能改善上,正式的版本将在数周后随着谷歌 Chrome 80 稳定版一起发布. V8 是谷歌公司推出的开源高性能 JavaScript 引擎,主要用于提升 Web 浏览器内部 JavaScript 脚本执行的性能.V8 通过 C++ 语言编写,主要用在 Chrome 浏览器以及 Node.js 上,实现了对 ECMAScript 与 WebAssembly 的支