【问题标题】:What does "Always initialize object members in the same order" mean in regards to V8 optimizations?关于 V8 优化,“始终以相同的顺序初始化对象成员”是什么意思?
【发布时间】:2019-08-02 17:32:45
【问题描述】:

从此old article 阅读 V8(微)优化 并且有一个引用:

始终以相同的顺序初始化对象成员

问题:在下面的示例中,始终以相同的顺序初始化对象成员是什么意思?

function Point(x, y) {
  this.x = x; // this.x = x line first because x is the first arg
  this.y = y; // this.y = y line second because y is the second arg
}

var p1 = new Point(11, 22);
var p2 = new Point(33, 44);
// At this point, p1 and p2 have a shared hidden class
p2.z = 55;
// warning! p1 and p2 now have different hidden classes!

加长引号:

JavaScript 具有有限的编译时类型信息:类型可以在运行时更改,因此很自然地期望在编译时推理 JS 类型的成本很高。这可能会导致您质疑 JavaScript 性能如何能够接近 C++。但是,V8 在运行时为对象内部创建了隐藏类型;具有相同隐藏类的对象可以使用相同的优化生成代码。

在对象实例 p2 添加了额外的成员“.z”之前,p1 和 p2 在内部具有相同的隐藏类 - 因此 V8 可以为操作 p1 或 p2 的 JavaScript 代码生成单一版本的优化程序集。您越能避免导致隐藏类发散,您将获得更好的性能。

因此:

  • 在构造函数中初始化所有对象成员(这样实例以后就不会改变类型)

  • 始终以相同的顺序初始化对象成员

注意:我在 C++ 中发现了类似的问题,但我真的看不懂Why should I initialize member variables in the order they're declared in?

【问题讨论】:

  • 例如,如果您的构造函数有分支逻辑导致 xy 根据输入参数以不同的顺序初始化,那将违反您引用的建议。
  • 你能创建一个答案+例子吗...我还是不明白。

标签: javascript optimization v8


【解决方案1】:

V8 开发人员在这里。首先,这个 JavaScript 性能建议与 C++ 的成员初始化规则完全无关。它也与构造函数参数的顺序无关,即从引擎性能的角度来看,以下内容非常好:

function Point(x, y) {
  this.y = y;  // Nothing wrong with this.
  this.x = x;
}

“以相同顺序初始化成员”的意思是该类型的所有实例应该使用相同的初始化顺序。当它们都使用相同的简单构造函数时,这会自动发生——这很好,因为这意味着在大多数情况下,您不必担心这一点;你甚至不需要知道这些建议。

最常见的反例是使用对象字面量创建对象,而不关心其中属性的顺序。即使属性名称的 set 相同,隐藏类的顺序也很重要。考虑:

let p1 = {x: 1, y: 2};
let p2 = {y: 3, x: 4};
// p1 and p2 now have different hidden classes!
function get_x(point) { return point.x; }
get_x(point1);
get_x(point2);

get_x 中的point.x 加载现在需要处理两个隐藏类, 这比每次看到相同的隐藏类要慢一些。

“始终使用构造函数”是避免这种情况的一个很好的经验法则;然而这还不够精确,如下例所示:

function SillyPoint(x, y) {
  if (x >= y) {  // or any other condition
    this.x = x;
    this.y = y;
  } else {
    this.y = y;
    this.x = x;
  }
}
let p1 = SillyPoint(1, 2);
let p2 = SillyPoint(2, 1);

即使 p1 和 p2 使用相同的构造函数,它们也初始化了它们的 成员的顺序不同,所以他们有不同的隐藏类。 与上面的示例一样,这会使需要同时处理 p1 和 p2 的函数中的属性加载稍慢。

【讨论】:

    猜你喜欢
    • 2010-09-10
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 2010-12-09
    • 2012-02-10
    相关资源
    最近更新 更多