QuickJS 浅试

近期不断看到 QuickJS,他没有 JIT,那么是否可以解决 Node.js 中 V8 首次执行耗时显著增加的问题?

QuickJS 是一个小型、快速、可嵌入的 JavaScript 引擎,由 Fabrice Bellard 创建。它支持 ES2020 规范并包含了一些扩展,例如支持二进制数据类型和模块。 QuickJS 还包含一个可选的字节码编译器,可以将 JavaScript 代码编译为字节码以提高执行速度。

Node.js 中的问题

由于 Node.js 具有 JIT 特性,同一个函数多次执行时,第一次的执行时间会显著比后续的执行时间长。

例如下面的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function render() {
let html = '';

for (let i = 0; i < 100000; i++) {
html + i;
}
}

for (let i = 0; i < 100; i++) {
const log = i < 3 || i > 97;
log && console.time(`render ${i}`);
render();
log && console.timeEnd(`render ${i}`);
}

执行结果是这样的:

render 0: 7.43ms
render 1: 6.743ms
render 2: 0.631ms
render 98: 0.036ms
render 99: 0.03ms

前几次耗时会明显的长。这会有什么问题呢?在作为 web 服务时,如果是长尾代码路径,那么执行到这些路径时会显著变慢,导致服务响应超时。

QuickJS 没有 JIT,那么理论上每次执行时间应该可以比较稳定。

QuickJS

还是上面的脚本,只是 QuickJS 目前不支持 Performance API,我们先用 Date.now() 凑合一下。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function render() {
let html = '';

for (let i = 0; i < 100000; i++) {
html + i;
}
}

for (let i = 0; i < 100; i++) {
const log = i < 3 || i > 97;
const start = Date.now();
render();
log && console.log(Date.now() - start);
}

执行结果为:

18
17
18
17
18

可以看到 QuickJS 的耗时确实是相对稳定的。但这个耗时要比 Node.js 第一次执行还要慢。

所以并不能用 QuickJS 来代替 V8 解决首次执行的耗时问题,因为 QuickJS 相比 V8 本身太慢了。

QuickJS 的优势

QuickJS 虽然不能解决 Node.js 中 V8 首次执行耗时问题,但是它的优势主要在于体积小资源占用低,非常适合嵌入式场景下使用。