V8 JS引擎

article/2025/8/21 16:12:40

一.  Google开发V8

Google (丹麦)研发小组在 2006 年开始研发 V8 ,部分的原因是 Google 对既有 JavaScript 引擎的执行速度不满意, 

2008年推出chrome, 巨大的速度优势, 迅速占领市场2017chrome的市场占有达到59%. 

二.  常见JS引擎

JScript(IE6,IE7, IE8)

Chakra(IE9,IE10, IE11, IE Edge)

SpiderMonkey(Firefox)

JavaScriptCore(Safari)

V8(Chrome)

这些是业界常见的JS引擎

应用在IEJscript

Chakra应用在新版的IE

FireFoxSpiderMonkey

SafariJavascriptCore

chromeV8

V8的速度相比最慢的IE快多少呢?

2008年的刚发布chrome, 有数据表明快56.


三.  JS语言与native语言相比有哪些优势.

1.脚本语言是一行行代码直接在解释器中解释执行的.

而非脚本语言是要编译成二进制机器码执行的.

对于具有很多模块的大工程,

如果没有修改模块对接的接口, 则编译单独模块即可,

如果修改了模块对接的接口, 那么仅编译单独模块就会引起运行时错误.

所以修改了模块对接接口, 往往需要把相关模块全部重新编译.

以我们的客户端native模块打包为例, 服务器多线程编译, 仍然需要数十分钟.

chrome为例, 的所有模块编译一遍需要半天时间.

脚本语言少了编译的过程, 修改之后可以立即看到修改的结果.

2.弱类型,native语言的数据类型很多, C++为例.

C++有十几种类型,float, double, int,short, bool,char, wchar,string, 指针,

每一种类型有自己的特性, 如果不按照特性操作,

就会出现数据错误, 严重的导致异常, 进程崩溃, 系统崩溃等.

所以C++中对于函数传递参数有比较严格的要求,

需要清晰的定义数据结构, 函数参数的类型和数量.

好处是运行效率高, 节省内存和磁盘.

这对于编写和维护代码的人而言就有非常大的工作量,

所以开发效率也就低于脚本语言的开发.

3.安全, 这里所说的安全性是针对用户而言的,

JS一般运行在浏览器内, 访问能力就是承载它的JS引擎给予的.

所以一般情况下, 不会导致用户的进程崩溃, 更不会引起系统崩溃.

这也是为什么要使用webnative替换Vmpage的一个重要原因.

4.跨平台

JS引擎在哪里, JS就可以运行在哪里,

据北京框架组的徐云飞透露,

他们试着在mac客户端集成了JsEngine.dll

然乎把我们开发的JS应用上去, 也可以运行.


四. JS的性能问题

JavaScript 除了少数类型,

大部分是动态的对象, 允许在任何时间,

在对象上新增或是删除属性和方法,

所以属性和方法需要通过键值查表的方式查找访问.



五. native的性能优势

native语言往往变量是结构化的,

对象要么是类对象, 要么是单一类型的.

在编译期变量就知道了结构有多大, 属性有多少,

按照类型的大小和个数可以计算出内存块的偏移值,

根据偏移值就可以获取到属性,子成员, 子函数等.


六.  JS的性能优化

V8的性能优化主要包含四个点:

JIT( just in time):
意思是即时编译,

解释器直接产生可执行数据,不产生中间码.

垃圾回收:

精确回收, 相比保守的回收, 涉及减少碎片, 内存复用, 要经常移动内存块, 所以操作要复杂得多.

自动侦测需要释放的内存, 因为侦测有消耗, 所以分为新生代和老年代, 来区分不同的侦测频率.

内嵌缓存:

缓存查找属性的结果, 减少一次属性查找

对于短的函数直接以函数内的实现替换调用, 减少一次函数调用

隐藏类:

让相似的JS对象以native的数据结构的形态存在于内存之中.

从而加速对象的存取操作, 不过一旦数据需要出现结构性改变,

此时又会将数据转换成另一个隐藏类, 除非隐藏类无法支持下去.

七. V8 编译改进

这里详细解释一下编译过程

这里为了解释说明了三种过程, 分别是老的JS引擎

Java的混合模式, V8引擎的编译

首先代码是一个文本, 第一步需要经过语言分析器解析生成抽象语法树.

这个步骤三者都是需要的.

对于老的JS引擎, 生成的是字节码, 通过字节码编译器来运行.

字节码的执行效率要低于直接在CPU上运行的机器码.

于是Java做出了改进, 将字节码编译成机器码执行,

并且让这两种方式并存.

V8则是绕过了其中的字节码步骤, 直接生成机器码.

这样它的运行效率可以和native语言媲美.

然而, 由于这样拉长了编译时间拉长, 并且生成的机器码占用了更多的内存.


八. 抽象语法树

抽象语法树是通过对一段JS代码文本进行语法解析生成的对象和对象之间的操作关系.

九. V8编译机器码


十. V8 Ignition

JIT编译带来了内存占用的问题, 和编译器加长的问题.

于是在20174月改进了编译方法, Ignition新架构, 是支持混合模式的

混合的方式是将第一层调用编译成机器码, 第一层以上的调用编译成字节码.

十一. V8的隐藏类

让相似的JS对象以native的数据结构的形态存在于内存之中.

从而加速对象的存取操作, 不过一旦数据需要出现结构性改变,

此时又会将数据转换成另一个隐藏类, 除非隐藏类无法支持下去.

如图所示, 有一个对象如果它没有x, y, 那么它在的隐藏类是C0

当它增加了x, 隐藏类转变成C1, 通过C1可以快速查找到x的偏移

当它增加了y, 隐藏类转变成C2, 通过C2可以快速查找到y的偏移

十二. JS代码的性能

前面我们看到V8有几个主要的优化点,

根据这些优化点, 可以想象JS编码如果顺应这些优化点,

如果JS中有部分代码需要重点提升性能,

可以考虑使用如下方法.

对象的属性顺序确定, 就更容易获得隐藏类的优化

实例化之后再添加删除属性将触发隐藏类的更改,

所以最好一次就完成实例化, 其后尽量减少对属性的修改

重复的执行一个函数,

相比重复的顺序执行多个不同函数运行更快

避免键值不是自增的数字避免预分配大数组,

最好是按需从小到大的增长, 不要删除数组中段的元素,

这会使被优化成 native 数组的对象变得稀疏 .

十三. V8的创建和销毁

int main(int argc, char* argv[]) { 
v8::V8::InitializeICU(); 
v8::Platform* platform = v8::platform::CreateDefaultPlatform(); 
v8::V8::InitializePlatform(platform); 
v8::V8::Initialize(); 
v8::V8::SetFlagsFromCommandLine(&argc, argv, true); 
v8::Isolate* isolate = v8::Isolate::New(); 
v8::Isolate::Scope isolate_scope(isolate);
v8::HandleScope handle_scope(isolate);
v8::Handle<v8::Context> context = CreateShellContext(isolate);
v8::Context::Scope context_scope(context);
...
v8::V8::Dispose();
v8::V8::ShutdownPlatform();
delete g_platform;
}

上面的代码中, 

ICU  表示国际化字符处理

Platform  管理线程池和任务队列

Isolate  V8引擎实例

Isolate::Scope  确保Isolate单独执行

handle  对当前对象引用计数, 用于垃圾回收

context  是函数和对象的执行环境, 使得不同JS代码之间的运行不干扰, 一个Isolate可以运行多个context

Context::Scope   确保context单独执行

十四. V8的对象句柄


Handle提供了一个JS 对象在堆内存中的地址的引用.

V8垃圾回收器将回收一个已无法被访问到的对象占用的堆内存空间.

垃圾回收过程中, 回收器通常会将对象在堆内存中进行移动.

当回收器移动对象的同时, 也会将所有相应的Handle更新为新的地址.

当一个对象在JavaScript中无法被访问到,

并且也没有任何Handle引用它, 则这个对象将被当作"垃圾"对待.

回收器将不断将所有判定为"垃圾"的对象从堆内存中移除.

V8的垃圾回收机制是其性能的关键所在.

电影<<寻梦环游记>>中有一个片段, 叫猪皮哥的鬼魂听完一曲歌声后, 魂飞魄散.

解释是, 当活人的世界里, 如果没有一个人活人这个鬼魂, 他就会消失.

如果这是真的, 那么鬼魂的世界里就有一个垃圾回收器通过计数来回收鬼魂.

上图中, 除了persistenthandle需要手动调用Reset释放计数,

其它handle都是在程序运行到它作用域之外时, 自动释放计数

十五. V8 template对象

    v8::Handle<v8::Context> CreateShellContext(v8::Isolate* isolate) {v8::Handle<v8::ObjectTemplate> temp = v8::ObjectTemplate::New(isolate);temp->Set(v8::String::NewFromUtf8(isolate, "print"),v8::FunctionTemplate::New(isolate, Print));temp->Set(v8::String::NewFromUtf8(isolate, "read"),v8::FunctionTemplate::New(isolate, Read));temp->Set(v8::String::NewFromUtf8(isolate, "quit"),v8::FunctionTemplate::New(isolate, Quit));temp->Set(v8::String::NewFromUtf8(isolate, "version"),v8::FunctionTemplate::New(isolate, Version));return v8::Context::New(isolate, NULL, temp);}

在一个context,

templateJavaScript函数和对象的模型.

你可以使用template来将 C++ 函数和数据结构封装在一个JavaScript对象中,

这样它就可以被JS 代码操作

通过set可以绑定函数到JS对象.

Chrome使用 templateC++DOM 节点封装成JS 对象.

JsEngine也使用templateC++函数封装到JS对象.

template如果是设置在global命名空间,

则可以被多个context复用.

另外template还可以通过SetAccessor绑定GetSet,

可以在JS访问到native中的属性.

设置拦截则是在属性在JS中被访问时调用

    v8::Handle<v8::Context> CreateShellContext(v8::Isolate* isolate) {v8::Handle<v8::ObjectTemplate> temp = v8::ObjectTemplate::New(isolate);temp->SetAccessor(String::NewFromUtf8(isolate, "y"), YGetter, YSetter);temp->SetNamedPropertyHandler(MapGet, MapSet);return v8::Context::New(isolate, NULL, temp);}

十六. 执行和异常

     v8::Local<v8::Context> context = v8::Local<v8::Context>::New(isolate_, context_);v8::Context::Scope context_scope(context);v8::Handle<v8::String> basescript = v8::String::NewFromUtf8(isolate_, strJsContent.c_str());v8::Local<v8::Script> compiled_script = v8::Script::Compile(basescript);TryCatch trycatch(isolate);Local<Value> v = compiled_script ->Run();if (v.IsEmpty()) {Local<Value> exception = trycatch.Exception();String::Utf8Value exception_str(exception);printf("Exception: %s\n", *exception_str);}


http://chatgpt.dhexx.cn/article/GF21cylk.shtml

相关文章

前端深度之Chrome的V8引擎内存详解

内容&#xff1a;V8引擎、JS内存管理、V8引擎如何回收垃圾、如何查看V8内存使用情况、内存优化实例 目录 一、V8引擎是什么&#xff1f; 二、内存 2.1、内存生命周期&#xff1a;&#xff08;这个不同的程序语言基本一样&#xff09; 2.2、JavaScript的内存管理 2.3、为什…

linux硬盘格式改为xfs,如何给Linux系统配置XFS文件系统

现在的系统基本都配备了XFS文件系统,XFS文件系统因其优秀且功能丰富而使用的人数很多,下面小编就给大家介绍下Linux下如何配置XFS文件,给想要配置XFS的朋友做个参考。 一、XFS文件系统简介 主要特性包括以下几点: 数据完全性 采用XFS文件系统,当意想不到的宕机发生后,首先…

xfs_growfs

LVM扩容 1 检查当前使用情况 df -h lvs vgs 2 在线扩容/opt lvextend -L 100GB /dev/mapper/VolGroup-opt xfs_growfs /dev/mapper/VolGroup-opt 3 扩容后检查 lvs df -hdf -hT lvslvextend -L 100GB /dev/mapper/VolGroup-optxfr_growfs /dev/mapper/VolGroup-optdf -hT # xf…

linux7xfs,RHEL7--XFS FileSystem

XFS 介绍 在RHEL7中&#xff0c;把XFS作为一种高可用性&#xff0c;高扩展性的文件系统已经列为默认的首先文件系统类型 XFS支持元数据日志记录&#xff0c;支持在线的扩容和整理. 可用采用 mkfs.xfs device 来进行格式 XFS Quota Management xfs能够汇报出在用户&#xff0c…

时代催生枭雄——XFS应运而生

站在人类发展进程的角度&#xff0c;全球新冠肺炎疫情大势横行&#xff0c;促进了百年未有之大变局加速演变&#xff0c;全球原有格局打破&#xff0c;新型的世界秩序正在重塑&#xff0c;世界又站在了历史的十字路口。 中国经济的发展需要良好的营商环境&#xff0c;对虚拟货…

Linux之XFS文件恢复

xfs类型文件备份恢复 我们使用的centos 7 默认使用的是xfs 类型文件系统&#xff0c;可以用xfsdump 与 xfsrestore 工具进行备份恢复。 xfsdump 的备份级别&#xff1a;0 &#xff1a;表示完全备份。1-9 表示增量备份。xfsdump 的备份级别默认为0。 xfsdump 的命令格式&…

xfs mysql_XFS文件系统与mysql应用性能测试

XFS 最初是由 Silicon Graphics&#xff0c;Inc. 于 90 年代初开发的。那时&#xff0c;SGI 发现他们的现有文件系统(existing filesystem&#xff0c;EFS)正在迅速变得不适应当时激烈的计算竞争。为解决这个问题&#xff0c;SGI 决定设计一种全新的高性能 64 位文件系统&#…

关于XFS文件系统概述

前言: 目前XFS已成为Linux主流的文件系统,所以有必要了解下其数据结构和原理。 XFS文件系统 XFS是一个日志型的文件系统,能在断电以及操作系统崩溃的情况下保证数据的一致性。XFS最早是针对IRIX操作系统开发的,后来移植到linux上,目前CentOS 7已将XFS作为默认的文件系统…

XFS 文件系统 (一) :设计概览

文章目录 0 前言1 设计背景2. 需要解决的问题2.1 异常恢复太慢2.2 不支持大文件系统2.3 不支持大型稀疏文件2.4 不支持大型连续文件2.5 不支持大目录2.6 不支持过多文件个数 3 XFS 架构4 痛点解决4.1 Allocation Groups4.2 Manging Free Space4.3 大文件的支持 5 总结 0 前言 …

linux常见实战(一)--【基于centos7的磁盘操作(新磁盘挂载/已有磁盘扩容)】

文章目录 前言&#xff1a;磁盘与文件系统1.xfs2.ext4 一、新磁盘的挂载1.查看已挂载磁盘情况2.查看所有磁盘情况3.给新磁盘分区4.格式化磁盘5.挂载磁盘6.设置开机自动挂载7.测试重启后挂载状态 二、对已有磁盘进行扩容1.查看磁盘挂载情况、分区情况2.进入磁盘进行分区操作3.格…

更快更好的Linux文件系统:XFS

XFS一种高性能的日志文件系统&#xff0c;最早于1993年由Silicon Graphics为他们的IRIX操作系统而开发&#xff0c;是IRIX 5.3版的默认文件系统。2000年5月&#xff0c;Silicon Graphics以GNU通用公共许可证发布这套系统的源代码&#xff0c;之后被移植到Linux 内核上。XFS极具…

Centos7使用

目录 一.材料准备 二.安装VM 三.创建虚拟机 四.进入CentOS安装界面 五、最小化必要的一些工具 一.材料准备 1.VMware-workstation 16版本 2.CentOS-7 64位光盘映像文件 二.安装VM 略 三.创建虚拟机 1.打开VMware Workstation&#xff0c;点击创建虚拟机 2.选择自定义…

CentOS7安装MySQL8

文章目录 一 前言二、Centos 7 安装 mysql8 步骤&#xff1a;1.下载MySQL官方的 Yum Repository2.安装方法一&#xff1a; 用wget 下载后安装方法二&#xff1a;下载 RMP 软件包将该软件包上传到 Linux 服务器&#xff0c;并安装。 3.Navicate 远程连接配置 一 前言 最近在自己…

CentOS7的安装流程

CentOS7的安装流程 1、 环境准备 安装VMware 下载Centos7镜像文件 2、 CentOS7安装流程 步骤一&#xff1a;打开VMware&#xff0c;点击创建新的虚拟机 步骤二&#xff1a;选择典型安装&#xff0c;点击下一步 步骤三&#xff1a;选择稍后安装操作系统&#xff0c;点击…

centos7安装教程

centos7安装教程&#xff1a;首先下载“CentOS-7-x86_64-bin-DVD1.iso”镜像文件&#xff1b;然后依次选择“文件->新建虚拟机->自定义”&#xff1b;接着根据向导进行虚拟机的创建&#xff1b;最后进入CentOS安装界面并进行安装设置即可。 本文操作环境&#xff1a;cent…

Linux-CentOS7安装教程【附CentOS7镜像】

Linux-CentOS7安装教程【附CentOS7镜像】 1. 新建虚拟机 点击“创建新的虚拟机” 点击“下一步” 选择“稍后安装操作系统”&#xff0c;点击“下一步” 选择"CentOS 7 64"&#xff0c;点击“下一步” 起一个虚拟机名字&#xff0c;设置一个合适的安装位置&#xf…

CentOS7安装git

CentOS7安装git 前言一、git介绍二、使用yum安装git1.安装git2.查看git版本3.移除git 三、源码包安装git1.安装依赖2.下载源码包3.解压4.git安装5.查看git版本 总结 前言 CentOS7安装git&#xff0c;刚开始使用yum安装git&#xff0c;发现安装的版本默认是1.8.3.1&#xff0c;…

centos7操作大全

不要走朋友,下面有很多安装教程&#xff08;注意查阅目录&#xff09; 基础命令 #查看cnetos7版本 cat /etc/centos-release #更改密码 passwd #(root指的是用户名&#xff0c;也可以不指定&#xff0c;默认更改当前用户) passwd root #删除文件命令 rm -f example.txt #删除…

CentOS7安装及配置

CentOS7安装及配置 1、安装CentOS7 打开VMware&#xff0c;选择创建新的虚拟机 选择典型&#xff0c;点击下一步 选择“稍后安装操作系统”&#xff0c;点击下一步 客户机操作系统选择“Linux”&#xff0c;版本选择“CentOS 7 ”&#xff0c;点击下一步填写虚拟机名称及其安…

Centos7 入门

Centos7 入门 目录 Centos7 入门1.3.注意事项创建虚拟机系统安装2.3.远程连接2.3.1.安装FinalShell 3.设置IP、网关、DNS、镜像3.1.设置IP3.2.设置主机名3.3.切换国内&#xff08;163&#xff09;镜像3.4.minimal版本安装系统组件3.5.同步时间3.5.1.安装3.5.2.设置为开机启动3.…