【问题标题】:Determining cause of deoptimisation确定去优化的原因
【发布时间】:2015-07-22 05:14:47
【问题描述】:

首先,问题:

如何确定我的函数未优化的原因?

例如,这是我的一个函数的去优化条目:

[deoptimizing (DEOPT eager): begin 0x3ca09e9f4d1 mergeObjects (opt #50) @12, FP to SP delta: 96]
            ;;; jump table entry 8: deoptimization bailout 12.
  translating mergeObjects => node=43, height=64
    0x7fff5fbfecd0: [top + 128] <- 0xcd290004121 ; [sp + 144] 0xcd290004121 <undefined>
    0x7fff5fbfecc8: [top + 120] <- 0x3ca09e9ca19 ; [sp + 136] 0x3ca09e9ca19 <an Object with map 0x4c8d818621>
    0x7fff5fbfecc0: [top + 112] <- 0x2c9b8b1b95a9 ; [sp + 128] 0x2c9b8b1b95a9 <an Object with map 0x7e33a207821>
    0x7fff5fbfecb8: [top + 104] <- 0x2c9b8b1b9229 ; rax 0x2c9b8b1b9229 <JS Array[0]>
    0x7fff5fbfecb0: [top + 96] <- 0xcd290004181 ; [sp + 112] 0xcd290004181 <false>
    0x7fff5fbfeca8: [top + 88] <- 0x2481f54fb4b6 ; caller's pc
    0x7fff5fbfeca0: [top + 80] <- 0x7fff5fbfed40 ; caller's fp
    0x7fff5fbfec98: [top + 72] <- 0x3ca09e8eae1; context
    0x7fff5fbfec90: [top + 64] <- 0x3ca09e9f4d1; function
    0x7fff5fbfec88: [top + 56] <- 0x70a69429aa1 ; [sp + 32] 0x70a69429aa1 <String[3]: key>
    0x7fff5fbfec80: [top + 48] <- 0xcd290004121 <undefined> ; literal
    0x7fff5fbfec78: [top + 40] <- 0xcd290004121 <undefined> ; literal
    0x7fff5fbfec70: [top + 32] <- 0x3ca09e9ca19 ; [sp + 136] 0x3ca09e9ca19 <an Object with map 0x4c8d818621>
    0x7fff5fbfec68: [top + 24] <- 0x4c8d818621 ; [sp + 64] 0x4c8d818621 <Map(elements=3)>
    0x7fff5fbfec60: [top + 16] <- 0x2c9b8b014341 ; [sp + 56] 0x2c9b8b014341 <FixedArray[3]>
    0x7fff5fbfec58: [top + 8] <- 0x300000000 ; [sp + 48] 3
    0x7fff5fbfec50: [top + 0] <- 0 ; [sp + 40] (smi)
[deoptimizing (eager): end 0x3ca09e9f4d1 mergeObjects @12 => node=43, pc=0x2481f54ecd00, state=NO_REGISTERS, alignment=no padding, took 0.060 ms]
[removing optimized code for: mergeObjects]

我怀疑原因,虽然不是很清楚,是这样的:

跳转表条目 8:去优化 bailout 12。

我在哪里可以找到更多关于这个和其他去优化原因的信息?更重要的是,我如何确定我的 JS 代码的哪一部分导致了这种去优化?

以下是我看到的其他功能的一些其他去优化原因:

  • deoptimize: Insufficient type feedback for generic named access
  • deoptimize: Insufficient type feedback for RHS of binary operation
  • jump table entry X: deoptimization bailout Y. - 很多都是不同的数字

用外行的话来说,我希望能够查看这个日志并说“好吧,我的函数被取消优化了,因为 v8 预测我只会使用字符串作为它的函数参数,在这里我用一个整数调用它”(或类似的东西)。

我还想了解更多关于我可以在这些日志中看到的其他信息 - 例如,各种去优化意味着什么(渴望、软等)?第一行的数字是什么意思?在提高性能的同时,我在此日志中还应该关注什么?

如果有任何相关性,上面日志中被取消优化的代码是here,要生成日志(通过运行库的基准测试),请在项目的根目录中执行:

node --trace_deopt --code_comments bench

【问题讨论】:

  • 你是如何从节点获得输出的?看起来很有趣。
  • 我已更新答案以包含该信息。这些是 v8 的选项 - 例如,您可以在 Node 的 manpage 上查看所有选项,或者运行 node --v8-options
  • 如果您的节点足够新(最好是 io.js,但我认为 0.12 也可以)那么您可以使用 IRHydra - mrale.ph/irhydra/2
  • @VyacheslavEgorov 我认为您可以将其发布为答案。我最近尝试过 Hydra,看起来它是目前可用于这些目的的最好的东西。

标签: javascript node.js optimization v8


【解决方案1】:

Petka Antonov(蓝鸟的创造者)describes some optimization killers here。我不知道如何解释您的 V8 输出,但 your code 确实包含一个 for-in 循环,在某些情况下可能会导致去优化。例如,如果被迭代的对象在hashtable mode 中。来自文章:

当您动态添加太多属性(在构造函数之外)、删除属性、使用不能是有效标识符的属性等时,对象将进入哈希表模式。换句话说,当你把一个对象当作一个哈希表来使用时,它就会变成一个哈希表。将这样的对象传递给 for-in 是不行的。当在 Node.JS 中启用标志 --allow-natives-syntax 时,您可以通过调用 console.log(%HasFastProperties(obj)) 来判断对象是否处于哈希表模式。

这种级别的 V8 优化确实看起来像是某种黑暗艺术 :) 希望有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-10-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-07
    • 2016-04-12
    • 1970-01-01
    相关资源
    最近更新 更多