为什么这个新代码比我的旧代码慢?

时间:2013-02-28 19:03:35

标签: javascript google-chrome optimization garbage-collection v8

问题

我已经用一些我原本希望表现更好的新代码替换了一些我遇到性能问题的代码。相反,它表现得更糟。我想了解为什么会这样,以便我可以使用chrome的V8运行时而不是它。

背景

我的代码适用于基于浏览器的游戏。在正常操作期间,许多xy坐标在函数之间传递。在我“修复”事物之前的一个例子看起来像这样:

function doSomething1(x,y) {
    /* Do work here */
    return {x: newx, y: newy};
}

function doSomething2(x,y) {
    /* Do work here */
    return {x: newx, y: newy};
}

function doSomething3(x, y) {
    var result1 = doSomething1(x, y);
    var result2 = doSomething2(result1.x, result1.y);

    /* Do work here */
    return {x: newx, y: newy};
}

你明白了......很多函数互相调用,返回带有xy属性的小匿名对象,并从中取出值。

当我的游戏运行时,它有垃圾收集问题。内存图非常灵巧,帧速率也不平滑。为了缓解这种情况,我决定重新编写代码,使其遵循以下模式:

function doSomething(x,y,out) {
    /* Do work here */
    out[0] = newx;
    out[1] = newx;
}

var xy = [0,0]; /* Some 2-length array for results */
doSomething(5,6,xy);
/* 'Return' value in xy */

通过这种方式,只有一个“分配”,并且在数组中将值替换为链中的函数。

这确实具有平滑内存分配图的效果。它还具有意想不到的副作用,即将帧率降低50%!!

为什么会这样?我可能正在绕过哪些优化措施?如何更好地编写此代码以使用V8运行时?

更新

进一步调查显示,该代码实际上并没有慢50%。当新代码托管在127.0.0.1上并且旧代码在互联网上时,它只会慢一些。这很奇怪,但不是同一个问题。我将结束这个问题。

1 个答案:

答案 0 :(得分:0)

写作时

out[0] = newx

V8只知道分配一个带有'0'字段的新对象并将newx加入其中。当你继续

out[1] = newy

它必须追踪它刚刚分配的对象,并为“1”字段分配更多空间。这比{x: newx, y:newy}贵很多,因为在后一种情况下,V8已经知道将会有多少个字段。

我不太了解优化javascript或游戏,因此我很难提出进一步的建议。希望你已经看过算法问题,现在正试着做一些微调 - 算法是可以做出重大改进的地方。