为什么这个新代码比我的旧代码慢?
问题描述:
我已经取代了我在与我的预期有更好的表现了一些新的代码的性能问题的一些代码的问题。相反,它表现更差。我想了解为什么会出现这种情况,以便我可以使用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和Internet上的旧代码时才会变慢。这很奇怪,但不是同一个问题。我将结束这个问题。
答
当你写
out[0] = newx
V8只知道要分配一个新对象与“0”领域,坚持newx
进去。当你继续
out[1] = newy
它必须跟踪它刚刚分配的对象,并为'1'字段分配更多的空间。这比{x: newx, y:newy}
贵很多,因为在后一种情况下,V8已经知道将会有多少个字段。
我对优化JavaScript或您的游戏了解不多,因此我很难进一步提出建议。希望你已经看过算法问题,现在正试图做一些微调 - 算法是可以做出重大改进的地方。
一个可能的原因是,你使用'out'数组和动态大小。你可以尝试创建一个固定大小的数组,并让我们知道结果:)你还没有提到你有多少元素,你可以添加这些信息吗? – Warlock 2013-02-28 19:12:45
“不成熟的优化是万恶之源” - Donald Knuth – Warlock 2013-02-28 19:21:04