函数包装器相对于类的性能基准测试与仅构造函数调用调用和HaveSameMap的性能基准比较



我用CODE A和CODE B进行了一些性能测量,想知道V8为什么会这样输出。

代码A

const makePoint = () => {
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
return new Point(1, 2);
}
const a = makePoint();
const b = makePoint();
console.log(%HaveSameMap(a, b)); // false

第一个问题,为什么HaveSameMap会返回false。我相信a和b都有相同的形状,经历相同的过程。那么,为什么它们会有所不同呢?

代码B

class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
var a = new Point();
var b = new Point();

第二个问题-比较两者的性能时间有很大的差异。我只想了解V8类型系统的基础。为什么它会这样做。调用new Point()与在makePoint()函数内返回它。这是怎么回事?

更新-测试方法

我正在通过外部包装进行测试

我的测试代码看起来像

const { performance } = require('perf_hooks');
performance.mark('start');
while (iterations--) {
makePoint();
}
performance.mark('end');
performance.measure('My Special Benchmark', 'start', 'end');

您在每次调用makePoint时都会创建一个新的Point类。当您直接返回类时,这可能会变得更加明显:

const makePoint = (x, y) => {
class Point {...};
return Point;
}

每次计算类文字时都会创建一个类。当在类定义之前添加console.log时,您可以在某种程度上看到这种情况。在您的情况下,每次都会进行评估。

类似地,每次创建一个新类的成本比简单地重新使用同一个类要高。V8必须创建大量内部数据结构来支持快速创建实例。一次使用一个类可以克服这种常见的模式,即你看到的减速。

在您的第一个代码段中,您不仅在makePoint中创建了实例,而且在class Point中也创建了实例本身。每次调用makePoint(),都会创建一个新类:

console.log(makePoint().constructor === makePoint().constructor) // false

我想你在找

class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
const makePoint = () => new Point(1, 2);
const a = makePoint();
const b = makePoint();
console.log(%HaveSameMap(a, b)); // true
console.log(a.constructor == b.constructor, a.constructor == Point); // true, true

最新更新