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

时间:2017-04-12 14:41:21

标签: javascript node.js performance performance-testing

我想知道在创建一个具有8个以上属性的对象时,NodeJS有任何限制吗?我做了一个基准测试,似乎对象有超过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;
});

环境:

  • Windows_NT 6.1.7601 x64
  • Node.JS: 6.9.5
  • V8: 5.1.281.89
  • Intel(R)Core(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();

1 个答案:

答案 0 :(得分:8)

据我所知 - 是的。

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

  • 使用有限数量的道具快速
  • 使用无限制道具缓慢

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

如果属性数量超过此限制 - 它会将对象重建为更慢的形式,但允许在其中包含无限数量的道具。

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

PROOF:

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

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

引擎为8 elements in fixed array by default

分配空间

固定数组已满 - 对象为rebuilt into dictionary here

原型和系统对象总是很快,当固定数组已满时,它们会使用不同的rebuilding procedure