如果数量大于8的道具,为什么NodeJS对象创建的性能如此糟糕?

Ice*_*bob 4 javascript performance performance-testing node.js

我想知道NodeJS在创建一个具有8个以上属性的对象时有任何限制吗?我做了一个基准测试,似乎对象有超过8个属性,性能会很糟糕.

测试套件:https://github.com/icebob/js-perf-benchmark/blob/master/suites/properties.js(问题末尾的完整副本)

结果:

  • 用1 prop 0%(62,695,620 rps)创建对象(平均值:15ns)
  • 使用8 prop -31.95%(42,662,752 rps)创建对象(平均值:23ns)
  • 使用9 prop -95.79%(2,640,046 rps)创建对象 (平均值:378ns)

码:

bench.add("Create object with 8 prop", () => {
    let opts = {
        prop1: 5,
        prop2: "",
        prop3: false,
        prop4: 1,
        prop5: 0,
        prop6: null,
        prop7: "Hello",
        prop8: 12345
    };
    return opts;
});

bench.add("Create object with 9 prop", () => {
    let opts = {
        prop1: 5,
        prop2: "",
        prop3: false,
        prop4: 1,
        prop5: 0,
        prop6: null,
        prop7: "Hello",
        prop8: 12345,
        prop9: "asd"
    };
    return opts;
});
Run Code Online (Sandbox Code Playgroud)

环境:

  • Windows_NT 6.1.7601 x64
  • Node.JS:6.9.5
  • V8:5.1.281.89
  • 英特尔(R)酷睿(TM)i5-2400 CPU @ 3.10GHz×4

以下是上述链接测试套件的内容:

"use strict";

let Benchmarkify = require("benchmarkify");
let benchmark = new Benchmarkify("Object properties").printHeader();

let bench = benchmark.createSuite("Create object with many properties");

// ----

bench.add("Create object with 1 prop", () => {
    let opts = {
        prop1: 5
    };
    return opts;
});

bench.add("Create object with 8 prop", () => {
    let opts = {
        prop1: 5,
        prop2: "",
        prop3: false,
        prop4: 1,
        prop5: 0,
        prop6: null,
        prop7: "Hello",
        prop8: 12345
    };
    return opts;
});

bench.add("Create object with 9 prop", () => {
    let opts = {
        prop1: 5,
        prop2: "",
        prop3: false,
        prop4: 1,
        prop5: 0,
        prop6: null,
        prop7: "Hello",
        prop8: 12345,
        prop9: "asd"
    };
    return opts;
});

bench.add("Create object with 20 prop", () => {
    let opts = {
        prop1: 5,
        prop2: "",
        prop3: false,
        prop4: 1,
        prop5: 0,
        prop6: null,
        prop7: "Hello",
        prop8: 12345,
        prop9: "asd",
        prop10: false,
        prop11: 5,
        prop12: "",
        prop13: false,
        prop14: 1,
        prop15: 0,
        prop16: null,
        prop17: "Hello",
        prop18: 12345,
        prop19: "asd",
        prop20: false
    };
    return opts;
});

bench.run();
Run Code Online (Sandbox Code Playgroud)

And*_*kyi 8

据我所知 - 是的.

v8引擎中的对象有两个对象表示:

  • 快速有限的道具
  • 缓慢无限的道具

对于新对象,V8引擎默认为"FAST 8属性对象"分配内存,这应该涵盖大多数用例.

如果属性数量超过此限制 - 它将对象重建为更慢的形式,但允许在内部拥有无限数量的道具.

顺便说一下,这与新对象实例化无关(如new X()):时间V8引擎的时间重新计算新对象的道具数量(每个类/内部类型).因此,如果您的代码创建了复杂的类 - 引擎将默认为此类/内部类型创建具有更多属性的FAST对象.


证明:

有关V8引擎内存管理的详细信息,请访问http://jayconrod.com/posts/52/a-tour-of-v8-object-representation

对于没有类(如var a = {})构造的新对象- 所有属性都转到固定数组,在文章"Extra properties"中调用

默认情况下,引擎为固定数组中的8个元素分配空间

固定数组完成后 - 此处将对象重建为字典

原型和系统对象总是很快,当固定数组已满时,它们使用不同的重建过程.

  • *"原型和系统对象总是很快"*我认为你的意思是"通过构造函数创建的对象",而不是原型.原型只是对象.有趣的是,不仅使用ctor创建9个以上的prop对象比使用文字更快(由于你指出的原因),使用`Object.create(prototypeWithAllTheProps)`创建一个,然后将道具分配给obj比文字也是(但不如ctor快),这是奇怪的,因为对象仍然必须在其中创建道具(遮蔽其原型的副本).https://pastebin.com/mPrnaULS (2认同)