v8、libuv、JIT 笔记

101 阅读2分钟
  • v8:负责解析和执行 js
  • libuv: 负责异步事件处理
  • JIT: 即时编译。

简单架构图

+-------------------------------------+
|            Application Layer        |
|  (JavaScript 代码:如 fs、http 模块) |
+-------------------------------------+
|                Node Bindings        |  ↔ 桥接 JS 与 C++(通过 V8 API)
+-------------------------------------+
|      V8 引擎       |      Libuv      |
|--------------------|-----------------|
| - 解析 JS 代码     | - 事件循环      |
| - JIT 编译优化     | - 异步 I/O 操作  |
| - 内存管理         | - 线程池管理     |
| - 调用 Libuv 接口  | - 跨平台兼容层   |
+-------------------------------------+
|            操作系统底层(Linux/Windows)|
+-------------------------------------+

详细架构图

+---------------------------+     +---------------------------+
|        JavaScript 代码      |     |         Node.js API        |
|   (如 fs.readFile, http)    |-----| (将 JS 调用转给 C++ Bindings)|
+---------------------------+     +---------------------------+
                                |
                                ▼
+--------------------------------------------------------------------------+
|                              Node Bindings                              |
| (C++ 层,连接 JS 与底层库,如 node_file.cc 处理 fs 模块)                   |
+--------------------------------------------------------------------------+
                                |
                                ▼
+--------------------------------------------------------------------------+
|       V8 引擎 (JavaScript 运行时)         |       Libuv (异步 I/O 引擎)     |
|-------------------------------------------|------------------------------|
| - 解析/编译 JS 代码                       | - 事件循环 (Event Loop)       |
| - JIT 优化 (TurboFan/Ignition)            |   - Timers 阶段                |
| - 内存堆 (Heap 管理)                      |   - I/O Polling 阶段           |
| - 调用 Libuv API 发起异步请求              |   - Check/Close 阶段等         |
|                                           |                              |
|                                           | - 线程池 (Thread Pool, 默认4线程)|
|                                           |   - 处理文件 I/O、DNS 等阻塞操作  |
|                                           |                              |
|                                           | - 跨平台兼容层                  |
|                                           |   - epoll (Linux)             |
|                                           |   - kqueue (macOS)            |
|                                           |   - IOCP (Windows)            |
+--------------------------------------------------------------------------+
                                |
                                ▼
+---------------------------+
|     操作系统底层 (OS)       |
| (文件系统、网络、定时器等接口) |
+---------------------------+

image.png

JIT

  • 解释器(Interpreter) ‌:逐行解释执行代码(如早期的 JavaScript 引擎),启动快但执行慢。

  • 编译器(Compiler) ‌:提前将代码编译为机器码(如 C++),执行快但启动慢。

  • JIT(即时编译) ‌:‌运行时动态编译‌,结合两者的优势:

    • 快速启动(解释器先执行)。
    • 热点代码(Hot Code)被编译为机器码,提升性能。

JIT 的性能对比

阶段执行速度内存占用适用场景
解释执行(字节码)冷门代码、快速启动
编译优化(机器码)极快热点代码、长期运行任务

V8 JIT 的分层设计

V8 的 JIT 分为 ‌两层‌,逐步优化代码:

(1) Ignition(解释器 + 基线编译器)

  • 作用‌:快速生成并执行 ‌字节码(Bytecode) ‌。

  • 流程‌:

    1. 解析 JavaScript 代码生成 ‌AST(抽象语法树) ‌。
    2. 生成字节码‌:AST 被转换为紧凑的字节码(类似汇编指令)。
    3. 解释执行字节码‌:同时收集代码的 ‌执行频率‌ 和 ‌类型反馈(Type Feedback) ‌。
  • 优化目标‌:快速启动,减少内存占用。

(2) TurboFan(优化编译器)

  • 作用‌:将热点代码(频繁执行的代码)编译为 ‌高度优化的机器码‌。

  • 触发条件‌:

    • 函数被多次调用(如循环体)。
    • 代码的类型趋于稳定(通过类型反馈)。
  • 优化策略‌:

    • 内联缓存(Inline Cache) ‌:缓存对象属性的内存偏移,避免重复查找。
    • 隐藏类(Hidden Class) ‌:动态跟踪对象结构,加速属性访问。
    • 逃逸分析‌:消除不必要的内存分配。
    • 循环优化‌:展开循环、向量化计算等。
  • 去优化(Deoptimization) ‌:如果假设失效(如类型突变),回退到字节码。