重复分配的Javascript开销

时间:2012-07-15 16:40:48

标签: javascript optimization object allocation

我正在制作一个非常简单的游戏,仅仅是为了娱乐/练习,但我仍然想要编写好的代码而不管它现在有多简单,以防我想回到它并且只是为了学习

所以,在这种情况下,我的问题是:

对象分配涉及多少开销?解释器已经对此进行了优化吗?我将反复检查对象网格位置,如果它们仍在同一网格中,则不更新网格数组

if (obj.gridPos==obj.getCurrentGridPos()){
    //etc
}

但是,我应该保留一个外部的“工作”点对象,getCurrentGridPos()每次都会更改,还是每次都应该返回一个新的点对象?

基本上,即使创建点对象的开销在这种情况下不是那么重要,哪个更快?

编辑: 这个?每帧将调用每个对象

function getGridPos(x,y){
  return new Point(Math.ceil(x/25),Math.ceil(y/25));
}

//outside the frame by frame update function looping through every object each frame
tempPoint= new Point()

//and each object each frame calls this, passing in tempPoint and checking that value
function makeGridPos(pt,x,y){
  pt.x = Math.ceil(x/25);
  pt.y = Math.ceil(y/25);
}

4 个答案:

答案 0 :(得分:1)

这个问题非常难以回答,因为所有不同的javascript引擎都在那里。 “4大”浏览器都有自己的javascript引擎/解释器,每个人都要进行分配,缓存,GCing等等。

Chrome(和Safari)开发工具有一个分析选项卡,您可以在其中分析代码的内存分配,计时等。这将是一个开始的地方(至少对于Chrome和Safari而言)

我不确定IE或Firefox是否提供此类工具,但如果这些浏览器存在某些第三方工具来测试此类工具,我不会感到惊讶......

另外,供参考 -

  • Chrome使用V8 javascript引擎
  • I.E使用Triton(我认为它仍然被称为?)javascript引擎
  • Firefox我相信使用Spidermonkey
  • Safari我不确定,但认为它使用的是WebKit的一部分。

答案 1 :(得分:1)

我的理解是垃圾收集在大多数JS引擎上停止执行。如果你要在游戏循环中每次迭代制作许多对象,并让它们超出范围,这将导致垃圾收集器接管时减速。

对于这种情况,您可以考虑通过删除所有属性,将__proto__重置为Object.prototype并将其存储来制作单个用于汇总对象的方法来回收它们以便重复使用在数组中。然后,您可以根据需要从池中请求回收的对象,仅在干燥时增加池大小。

答案 2 :(得分:1)

在您现在添加的两个代码示例之间,我不知道第一个代码示例的效率高于第二个代码示例。因此,如果您正在尝试优化性能或内存使用,那么重新使用现有对象可能比每次调用函数时创建新对象更有效。

注意:由于JS通过引用引用对象,因此您必须确保您的代码不会挂在该对象的其他位置,并期望它保持其值。


先前的回答:

在所有编程中(无论优化器有多好),您总是可以更好地缓存由于访问在同一函数中反复使用的多个成员变量而计算的结果,而不是调用该函数一遍又一遍地计算。

因此,如果您多次调用obj.getCurrentGridPos()并且条件没有发生变化以致可能返回不同的结果,那么您应该在本地(以任何语言)缓存它的值。这只是一个很好的编程。

var currentPos = obj.getCurrentGridPos();

然后,使用该本地缓存的值:

if (obj.gridPos == currentPos) {

解释器可能无法为您执行此类优化,因为它可能无法判断其他操作是否可能导致obj.getCurrentGridPos()返回与另一个调用不同的内容,但是程序员可以知道那个。

另一件事。如果obj.getCurrentGridPos()返回实际对象,那么您可能不希望使用=====来比较对象。这只是比较,看它们是否确实是同一个对象 - 它不能比较两个对象是否具有相同的属性。

答案 3 :(得分:0)

简短的回答是设置一个current position对象并检查自身,因为如果每次调用getCurrentGridPos()时创建一个新对象,你将会使用更多内存。

is this a new position检查可能有一个更好的位置,因为每次迭代只应进行一次检查。

使用RequestAnimationFrame设置currentGridPos似乎是最佳的,并在更新之前检查其当前x y z位置,以便您可以触发changedPosition类型事件。< / p>

var currentPos = {
    x:0,
    y:0,
    z:0
}
window.requestAnimationFrame(function(newPos){
    if (currentPos.x != currentPos.x || currentPos.y != currentPos.y || currentPos.z != newPos.z) {
        $.publish("positionChanged"); // tinypubsub https://gist.github.com/661855
    }
})

所以,为了清楚,是的,我认为你应该保留一个外部的“工作”点对象来更新每次迭代......当它更新时你可以检查它的位置是否已经改变 - 这将是一个更多有意识地组织逻辑并确保每次迭代不要多次调用getCurrentPos