Skip to content

V8引擎概述

约 2348 字大约 8 分钟

浏览器前端JavaScriptV8

2025-05-22

1.引入

在了解V8引擎之前首先先了解以下方面的概念

  • 传统编译执行

  • 解释执行

  • 即时编译

  • Self 基于原型(prototype)的继承机制

  • Scheme 的函数作为一等公民

1.1 传统编译执行

  • 传统编译执行:在程序运行之前,整个代码先被编译成机器码,然后直接执行。编译过程可能较长,但程序的执行速度较快。
    • 优点:执行速度快,适合长期运行的程序。
    • 缺点:启动慢,无法根据程序的运行时行为进行优化。

1.2 解释执行

​ 解释执行指的是程序代码在运行时,通过解释器的工具逐行分析和执行代码,而不需要将整个程序事先转换成机器码(即机器语言)执行。

执行过程可以理解为

  • 逐行执行:代码在运行时被逐行分析和执行。解释器会逐个读取源代码的每一行,理解该行的指令,并立即执行。
  • 即时处理:每行代码都要在运行时被“解释”,所以每次执行时,解释器都需要重复做同样的工作。

浏览器中的 JavaScript 引擎(如 V8)最初使用的是解释执行。

过程为

let a = 10;//读取 第一行 let a = 10;,然后将变量 a 的值设为 10
let b = 20;//读取 第二行 let b = 20;,然后将变量 b 的值设为 20。
let c = a + b;//读取 第三行 let c = a + b;,计算 a + b 的值,结果是 30,并将其赋值给 c
console.log(c);//读取 第四行 console.log(c);,执行 console.log,打印出 30

优点

  • 快速启动:因为没有编译过程,程序可以很快开始执行。适合快速开发和测试。
  • 灵活性:代码可以动态执行,支持动态语言特性(如动态类型、动态创建函数等)。

缺点

  • 性能较低:由于每行代码都需要在执行时被解析和执行,所以性能较差。每次执行时,解释器需要重新解析源代码并执行,这就导致了性能上的浪费。
  • 无法优化:相较于编译执行,解释执行的代码难以进行优化。因为代码并没有被转化为机器码,无法像编译器那样进行性能优化。

1.3 即时编译(JIT)

即时编译(JIT,Just-In-Time Compilation) 是一种将程序代码在运行时动态编译为机器码的技术。它结合了编译型语言和解释型语言的优点,旨在提高程序的执行效率。JIT 编译器会在程序运行时监视代码的执行监视代码的执行情况,将最常用(即“热点”)的代码段编译成高效的机器码,从而提升执行速度。

工作原理

  1. 初始解释执行:当程序第一次执行,不会直接将整个代码块转化为机器码,先进行解释执行,这种方式能够快速启动程序,减少启动时的延迟。
  2. 识别热点代码:JIT编译器运行会监控被频繁使用的代码块,并标记为热点代码。(eg.一个常用函数或者循环体)
  3. 编译热点代码:一旦被JIT识别到的热点代码就会被编译为机器码。
  4. **替换已编译的代码:**编译后的机器码会替代原来的解释执行代码,之后每次执行这些热点代码时,直接使用机器码,从而提高性能。
  5. 动态优化:JIT 编译器可以在运行时对代码进行进一步的优化。比如,当它发现某个代码块的执行模式发生变化时,会重新编译并应用优化策略,以适应新的执行模式。

1.4 Self 基于原型(prototype)的继承机制(待补充)

​ 见原型与原型链以及继承机制

1.5 Scheme 的函数作为一等公民

​ 简单理解:在 Scheme 等函数式编程语言中,函数是“一等公民”。这意味着函数可以像其他数据类型一样被传递、赋值、返回和操作。在 JavaScript 中,函数同样是“一等公民”,即可以作为参数传递给其他函数、作为返回值返回、并且可以动态创建和调用。

2.认识JavaScript引擎

2.1什么是JavaScript引擎?

​ JavaScript引擎是一个解释和执行JavaScript代码的程序,负责将JavaScript代码转换成可执行的机器代码。这个过程包括解析代码、进行优化,并最终执行。通过它,JS能在浏览器或服务器环境中运行,处理从简单的脚本到复杂应用的各种计算任务。

可以理解为将高级语言(JavaScript)转化为机器语言的工具。

2.2目前常见的JavaScript引擎

目前,常见的 JavaScript 引擎有:

  • V8 引擎:由 Google 开发,广泛应用于 Chrome 浏览器以及 Node.js 中。V8 采用了即时编译(JIT)技术,将 JavaScript 代码动态编译成机器码,优化了性能。
  • SpiderMonkey:由 Mozilla 开发,主要用于 Firefox 浏览器。SpiderMonkey 也是一个支持 JIT 编译的引擎,早期还支持解释执行。
  • Chakra:由微软开发,曾用于 Edge 浏览器。Chakra 引擎支持 JIT 编译,并通过优化技术提高执行效率。
  • JavaScriptCore(Nitro):由苹果开发,用于 Safari 浏览器。JavaScriptCore 也采用了 JIT 编译技术,并进行了许多优化。

Google是最先开发使用V8引擎,V8 是率先引入了即时编译(JIT)的双轮驱动的设计。

所以当时谷歌浏览器的浏览速度会快于其他浏览器的原因

3.V8引擎

3.1 V8引擎是什么?

​ V8 引擎是擎是由 Google 开发的一个高性能的 JavaScript 引擎,最初用于 Google Chrome 浏览器,现在也广泛应用于 Node.jsElectron 等平台中。V8 引擎的主要任务是将 JavaScript 代码转换为计算机可以执行的机器代码,并尽可能地优化执行速度。

3.2 V8 引擎的工作流程(待补充)

1.解析(Parsing)

  • V8 引擎首先会读取 JavaScript 代码,并将其转化为一种称为 抽象语法树(AST, Abstract Syntax Tree)的数据结构。
  • 在这个过程中,V8 会进行词法分析(lexical analysis)和语法分析(syntax analysis),将 JavaScript 代码从文本转化为计算机可以理解的结构。

2.生成字节码

  • 解析完成后,V8 会将 AST 转换成 字节码(bytecode)。字节码是一种介于机器码和源代码之间的中间表示,它适用于多种平台。
  • 字节码的好处是它比纯文本的源代码更接近机器语言,因此执行效率更高,但仍然是平台无关的。

3.即时编译(JIT 编译)

  • V8 引擎使用 即时编译(JIT, Just-In-Time compilation) 技术,将字节码转换为平台特定的机器代码。
  • Ignition 是 V8 的字节码解释器,负责将 JavaScript 代码执行为字节码。
  • TurboFan 是 V8 的优化编译器,负责将字节码转化为高度优化的机器码。这个过程通常发生在代码执行时,尤其是对于 "热代码"(即被频繁执行的代码)进行优化。

4.执行(Execution)

  • V8 引擎将生成的机器码交给 执行器(executor)来运行。机器码是可以直接在 CPU 上执行的代码,因此这一步是 V8 提高执行速度的关键。

5.垃圾回收(Garbage Collection)

  • 垃圾回收是 V8 引擎自动进行内存管理的机制。它回收不再使用的对象,以避免内存泄漏。
  • V8 使用 分代垃圾回收(Generational Garbage Collection) 技术,将对象按生命周期分为两类:年轻代和老年代,并为每类对象选择不同的回收策略。

3.3 V8 引擎的优化技术(待补充)

  1. 即时编译(JIT)
    • V8 的 JIT 编译器能够将 JavaScript 代码编译成机器码,在执行时进行动态优化。通过这种方式,V8 可以根据代码的运行情况进行实时优化。
  2. 内联缓存(Inline Caching)
    • 内联缓存是 V8 引擎的一种优化技术,用于加速对象属性的访问。它缓存了对象属性查找的结果,从而避免每次访问时都要遍历原型链。
  3. 类型反馈(Type Feedback)
    • V8 通过收集关于变量类型的反馈信息,来优化代码的执行。例如,它会根据变量实际的类型信息生成更高效的机器码。
  4. 函数内联(Function Inlining)
    • 函数内联技术将小的函数直接嵌入到调用点,避免了函数调用的开销。这样做可以提高性能,特别是当一个函数被频繁调用时。
  5. 增量垃圾回收(Incremental Garbage Collection)
    • 为了避免长时间的停顿,V8 引擎采用增量垃圾回收技术,将垃圾回收过程分为多个小步骤,每次只处理一小部分,从而减少停顿时间。