- 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) |
| (文件系统、网络、定时器等接口) |
+---------------------------+
JIT
-
解释器(Interpreter) :逐行解释执行代码(如早期的 JavaScript 引擎),启动快但执行慢。
-
编译器(Compiler) :提前将代码编译为机器码(如 C++),执行快但启动慢。
-
JIT(即时编译) :运行时动态编译,结合两者的优势:
- 快速启动(解释器先执行)。
- 热点代码(Hot Code)被编译为机器码,提升性能。
JIT 的性能对比
| 阶段 | 执行速度 | 内存占用 | 适用场景 |
|---|---|---|---|
| 解释执行(字节码) | 慢 | 低 | 冷门代码、快速启动 |
| 编译优化(机器码) | 极快 | 高 | 热点代码、长期运行任务 |
V8 JIT 的分层设计
V8 的 JIT 分为 两层,逐步优化代码:
(1) Ignition(解释器 + 基线编译器)
-
作用:快速生成并执行 字节码(Bytecode) 。
-
流程:
- 解析 JavaScript 代码生成 AST(抽象语法树) 。
- 生成字节码:AST 被转换为紧凑的字节码(类似汇编指令)。
- 解释执行字节码:同时收集代码的 执行频率 和 类型反馈(Type Feedback) 。
-
优化目标:快速启动,减少内存占用。
(2) TurboFan(优化编译器)
-
作用:将热点代码(频繁执行的代码)编译为 高度优化的机器码。
-
触发条件:
- 函数被多次调用(如循环体)。
- 代码的类型趋于稳定(通过类型反馈)。
-
优化策略:
- 内联缓存(Inline Cache) :缓存对象属性的内存偏移,避免重复查找。
- 隐藏类(Hidden Class) :动态跟踪对象结构,加速属性访问。
- 逃逸分析:消除不必要的内存分配。
- 循环优化:展开循环、向量化计算等。
-
去优化(Deoptimization) :如果假设失效(如类型突变),回退到字节码。