跳到主要内容

V8

V8 是为 Google Chrome 提供支持的 JavaScript 引擎的名称。 它是获取我们的 JavaScript 并在使用 Chrome 浏览时执行它的东西。

V8 是 JavaScript 引擎,即它解析和执行 JavaScript 代码。 DOM 和其他 Web 平台 API(它们都构成运行时环境)由浏览器提供。

很酷的是 JavaScript 引擎独立于托管它的浏览器。 这个关键特性促成了 Node.js 的兴起。 早在 2009 年,V8 就被选为支持 Node.js 的引擎,随着 Node.js 的爆炸式增长,V8 成为现在支持大量用 JavaScript 编写的服务器端代码的引擎。

Node.js 生态系统非常庞大,这要归功于 V8,它还支持桌面应用,包括 Electron 等项目。

其他 JS 引擎 其他浏览器有自己的 JavaScript 引擎:

Firefox 有 SpiderMonkey Safari 有 JavaScriptCore(也叫 Nitro) Edge 最初基于 Chakra,但最近改成了 使用 Chromium 重建 和 V8 引擎。

对性能的追求

V8 是用 C++ 编写的,并且在不断改进。 它是可移植的,可以在 Mac、Windows、Linux 和其他几个系统上运行。

在这篇 V8 介绍中,我们将忽略 V8 的实现细节: 它们可以在更权威的站点(例如 V8 官网)上找到,并且它们会随着时间的推移而发生变化,通常是根本性的。

V8 一直在发展,就像周围的其他 JavaScript 引擎一样,以加速 Web 和 Node.js 生态系统。

在 Web 上,性能竞赛已经持续多年,我们(作为用户和开发者)从这场竞赛中受益匪浅,因为我们年复一年地获得更快、更优化的机器。

https://github.com/HXWfromDJTU/blog/issues/25

编译

引擎处理流程优缺点
旧版 V8JavaScript 代码-> AST->V8 直接执行这些未优化过的机器码-> 高频率过高的代码优化为机器码① 惰性编译,编译时间久,影响代码启动速度
② 编译出的机器码通常为源 JS 代码大小的几千倍
③ 使用内存、硬盘进行缓存在移动端内存占用问题明显
新版 V8源代码 -> AST -> 字节码 -> 解释器执行字节码新版 v8 源代码 ---> AST ---> 字节码 ---> 解释器执行字节码 ① 字节码占用空间远小于机器码,有效减少内存占用
② 将字节码转换为不同架构的二进制代码的工作量也会大大降低
③ 引入字节码,使得 V8 移植到不同的 CPU 架构平台更加容

早期:未优化机器码 优化:高频代码直接记录为机器码

后期:改用字节码

字节码

  1. 解释器可以直接解释执行字节码。
  2. 字节码是一种中间码,占用内存相较机器码小,不受 cpu 型号影响。
  3. 机器码可以被 cpu 直接解读,运行速度快。
  4. 但是不同 cpu 有不同体系架构,也对应不同机器码。占用内存也较大

v8 流程(老版)

在 V8 中,JavaScript 代码的执行主要包括以下步骤:

  1. 词法分析:将 JavaScript 代码转换为一系列词法单元(token)。
  2. 语法分析:将词法单元转换为一棵语法树(Abstract Syntax Tree, AST)。
  3. 优化编译:对语法树进行优化编译,包括去除无用代码、提前计算常量、进行内联函数等操作,以便生成更加高效的机器码。
  4. 生成机器码:将优化后的代码生成机器码,并将其存储在代码缓存中,以便下次使用。
  5. 执行代码:执行机器码,将 JavaScript 代码转换为计算机能够理解的指令,执行相应的操

新版 V8 引擎

js 引擎(englie)实际就是翻译器,runtime(js 的 event loop)是执行,url 分配。 V8 执行 JavaScript 的原理,大致可以分为三个步骤: 解析器将 JavaScript 源码解析为 AST(runtime 的作用),解析过程分为词法分析和语法分析,V8 通过预解析提升解析效率; 解释器 Ignition(englie) 根据 AST 生成字节码并执行。这个过程中收集执行反馈信息,交给 TurboFan 进行优化编译; TurboFan 根据 Ignition 收集的反馈信息,将字节码编译为优化后的机器码,后续 Ignition 用优化机器码代替字节码执行,进而提升性能。

shell(url 分发数据,cpu 的部分功能),可以让用户输入命令并查看或者修改内存中的内容,以 16 进制来编程、检查一段代码的内容或者在特定地址运行一段程序,该 monitor 程序运行在一段 256 字节大小的内存空间中,你可以把 monitor 看做那个年代的操作系统(url 的作用)

V8 预解析

比如两个嵌套函数,只解析外层函数,内层函数只有外层函数执行时发现内层函数被用到时再解析 所以 V8 引擎就实现了 Lazy Parsing(延迟解析) 的方案,它的作用是将不必要的函数进行预解析,也就是只解析暂时需要的内容,而对函数的全量解析是在函数被调用时才会进行