gpt4 book ai didi

javascript - 为什么新的慢?

转载 作者:IT王子 更新时间:2023-10-29 03:20:47 26 4
gpt4 key购买 nike

基准:

JsPerf

不变量:

var f = function() { };

var g = function() { return this; }

测试:

以下按预期速度排序

  • new f;
  • g.call(Object.create(Object.prototype));
  • new (function() { })
  • (function() { return this; }).call(Object.create(Object.prototype));

实际速度:

  1. new f;
  2. g.call(Object.create(Object.prototype));
  3. (function() { return this; }).call(Object.create(Object.prototype));
  4. new (function() { })

问题:

  1. 当您将 fg 交换为内联匿名函数时。为什么 new(测试 4.)测试速度较慢?

更新:

fg 被内联时,具体是什么导致 new 变慢。

我对 ES5 规范或 JagerMonkey 或 V8 源代码的引用很感兴趣。 (也可以随意链接 JSC 和 Carakan 源代码。哦,如果 IE 团队愿意,他们可以泄露 Chakra 源代码)。

如果链接任何JS引擎源,请说明。

最佳答案

#4 和所有其他情况的主要区别在于,第一次使用闭包作为构造函数时总是非常昂贵。

  1. 它总是在 V8 运行时(而不是在生成的代码中)处理,并且在已编译的 JS 代码和 C++ 运行时之间的转换非常昂贵。后续分配通常在生成的代码中处理。您可以查看 builtins-ia32.cc 中的 Generate_JSConstructStubHelper 并注意当闭包没有初始映射时它会落入 Runtime_NewObject。 (参见 http://code.google.com/p/v8/source/browse/trunk/src/ia32/builtins-ia32.cc#138)

  2. 当第一次将闭包用作构造函数时,V8 必须创建一个新映射(也称为隐藏类)并将其分配为该闭包的初始映射。参见 http://code.google.com/p/v8/source/browse/trunk/src/heap.cc#3266 .这里重要的是 map 被分配在一个单独的内存空间中。这个空间不能被快速部分清除 收集器清理。当 map 空间溢出时,V8 必须执行相对昂贵的 full mark-sweep GC。

当您第一次使用闭包作为构造函数时,还会发生其他一些事情,但 1 和 2 是导致测试用例 #4 运行缓慢的主要原因。

如果我们比较表达式#1 和#4,那么差异是:

  • #1并不是每次都分配一个新的闭包;
  • #1 并非每次都进入运行时:在闭包获取初始 map 构造后,在生成代码的快速路径中进行处理。在生成的代码中处理整个构造比在运行时和生成的代码之间来回处理要快得多;
  • #1并不是每次都为每个新的闭包分配一个新的初始映射;
  • #1 不会因溢出 map 空间而导致标记清除(仅廉价的清除)。

如果我们比较#3 和#4,那么差异是:

  • #3 不会每次都为每个新的闭包分配一个新的初始映射;
  • #3 不会因溢出 map 空间而导致标记清除(仅廉价的清除);
  • #4 在 JS 方面做得更少(没有 Function.prototype.call,没有 Object.create,没有 Object.prototype 查找等)在 C++ 方面做得更多(#3 每次执行 Object.create 时也会进入运行时,但非常那里很少)。

这里的底线是,与 相同 闭包的后续构造调用相比,您第一次使用闭包作为构造函数的代价是昂贵的,因为 V8 必须设置一些管道。如果我们立即丢弃闭包,我们基本上就丢弃了 V8 为加速后续构造函数调用所做的所有工作。

关于javascript - 为什么新的慢?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6440661/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com