一个JS的class fields导致在v8 9.4(nodejs 16)上的性能退化的问题 | Blurred code

一个JS的class fields导致在v8 9.4(nodejs 16)上的性能退化的问题

2024/02/10

LastMod:2024/02/10

Categories: JavaScript PuerTs

最近仍然在做一些关于v8的性能测试,用到的v8的版本是9.4,对应nodejs的16版本。 在测试以下代码的时候发现一个有意思的性能问题。

class Point {
  X: number;
  Y: number;
  Z: number;
  constructor(x: number, y: number, z: number) {
    this.X = x;
    this.Y = y;
    this.Z = z;
  }
};

let start_time = new Date().getTime();
for (let i = 0; i < 100_0000; i++) {
  let p = new Point(1, 2, 3);
}
let end_time = new Date().getTime();
console.log("Time: " + (end_time - start_time) + "ms")

问题原因

v8 9.4在处理以下形式的js class声明的时候有性能问题,只要包含了class fields的声明,性能就会急剧劣化。

class Point {

    //=== class fields define
    X;
    Y;
    Z;
    //=== class fields define

    constructor(x, y, z) {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }
}
;

把tsc编译后的测试代码直接用node运行,

"use strict";
class Point {
    X;
    Y;
    Z;
    constructor(x, y, z) {
        this.X = x;
        this.Y = y;
        this.Z = z;
    }
}
;
let start_time = new Date().getTime();
for (let i = 0; i < 1000000; i++) {
    let p = new Point(1, 2, 3);
}
let end_time = new Date().getTime();
console.log("Time: " + (end_time - start_time) + "ms");

v8 9.4上运行的时间是275ms,在v8 10.2(node18)的运行时间是6ms

绕过方法

参考:#useDefineForClassFields 翻了下ts是在什么时候引入的class fields的生成,发现是在3.7版本引入的。 当编译目标为ES2022 or later/ ESNext的时候,就会自动生成class fields

可能的修复方案: