【问题标题】:Why is this new code slower than my old code?为什么这个新代码比我的旧代码慢?
【发布时间】:2013-02-15 02:50:35
【问题描述】:

问题

我已经用一些我期望性能更好的新代码替换了一些我遇到性能问题的代码。相反,它的表现更差。我想了解为什么会这样,以便我可以使用 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 和旧代码托管在互联网上时,它才会更慢。这很奇怪,但不是同一个问题。我会结束这个问题。

【问题讨论】:

  • 一个可能的原因是您使用了具有动态大小的“out”数组。您能否尝试创建具有固定大小的数组并让我们知道结果:)您还没有提到您有多少元素,您可以添加此信息吗?
  • “过早的优化是万恶之源” - Donald Knuth

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


【解决方案1】:

当你写作时

out[0] = newx

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

out[1] = newy

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

我对优化 javascript 或您的游戏知之甚少,因此我很难提出进一步的建议。希望您已经研究过算法问题,现在正尝试进行一些微调——算法是可以做出重大改进的地方。

【讨论】:

    猜你喜欢
    • 2018-11-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-24
    • 2023-03-28
    • 2021-01-24
    相关资源
    最近更新 更多