我见过的最奇怪的错误。可能的V8优化问题?

时间:2016-07-24 18:54:43

标签: javascript node.js optimization v8

很难解释这一点。我花了三天才弄明白。

我正在制作一个序列化库,而我正试图让它变速。它只是将对象序列化为缓冲区。

我注意到如果我先运行我的基准测试,那么编码需要大约500毫秒。但是,如果我先运行我的测试套件,那么之后我的基准测试需要大约1300毫秒来编码。

这非常奇怪,因为他们使用两个完全不同的对象进行操作,根本没有任何共享。

我完成了我的程序并开始对每一行进行基准测试,直到我最终找到了占800毫秒差异的行。

这是函数中的这一行:for (var j = arrLen; j < refLen; j++) {

也不是循环的主体。只是for循环的标题。

我不知道如何修复它。除了最近只是一时兴起我试图复制该功能(只是复制和粘贴)并重命名它在名称的末尾包含一个0。

然后我让我的测试套件调用第一个函数,我的基准测试调用第二个函数。时差消失了。功能内容和参数列表完全相同。

我的主要理论是:第一次调用此函数时,函数已经过优化,我想循环已展开。这就是为什么首先调用基准测试没有问题:因为第一次调用它时它会被优化。但是,如果稍后调用它,它不会针对给定的输入进行优化,因此运行速度非常慢。

我的问题是:只是复制和粘贴此功能数千次并且每个编码使用此功能的不同版本,有没有办法解决此问题以消除时间区别? 500毫秒到1300毫秒之间的差异很大。

我一直试图对此进行测试,但这非常困难,因为这个错误是如此模糊。希望我的文字描述足够了。

编辑:这是被调用的函数。

function endEncodeArray(ref, arrLen, writeRepeatFunction, wBuffer) {
  var refLen = ref.length;
  if (refLen - arrLen > 0) {
    for (var j = arrLen; j < refLen; j++) { // <-- this line slow
      writeRepeatFunction(ref[j], wBuffer);
    }
  }
}

编辑2:手动将函数写为字符串,评估它,然后调用它的方法似乎可以解决性能问题。由于我无法弄清楚如何隔离测试用例,我想我只是将其用作绷带修复。

1 个答案:

答案 0 :(得分:0)

您可能会面临deopt,因为您提到的基准测试和测试使用两个完全不同的对象。有关详细信息,请参阅http://mrale.ph/blog/2015/01/11/whats-up-with-monomorphism.html,希望有所帮助。