0

我正在制作一个非常简单的游戏,只是为了好玩/练习,但我仍然想把它编码好,不管它现在多么简单,以防我想回到它并只是为了学习

因此,在这种情况下,我的问题是:

对象分配涉及多少开销?解释器已经优化到什么程度了?我将反复检查对象网格位置,如果它们仍在同一个网格正方形中,则不更新网格数组

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

4 回答 4

1

这个问题很难回答,因为存在所有不同的 javascript 引擎。浏览器的“四大”都有自己的 javascript 引擎/解释器,每个浏览器都会以不同的方式进行分配、缓存、GCing 等。

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

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

另外,供参考-

  • Chrome 使用 V8 javascript 引擎
  • IE 使用 Triton(我认为它仍然叫那个?)javascript 引擎
  • Firefox 我相信使用 Spidermonkey
  • Safari 我不确定,但认为它使用的是 WebKit 的一部分。
于 2012-07-15T17:02:19.823 回答
1

据我了解,垃圾收集会在大多数 JS 引擎上停止执行。如果您要通过游戏循环每次迭代制作许多对象并让它们超出范围,这将导致垃圾收集器接管时速度变慢。

对于这种情况,您可能会考虑创建一个单例来使用一种方法来池您的对象,该方法通过删除它们的所有属性、将它们重置__proto__Object.prototype并将它们存储在一个数组中来回收它们以供重用。然后,您可以根据需要从池中请求回收对象,仅在池干涸时增加池大小。

于 2012-07-15T17:06:39.353 回答
1

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

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


之前的回答:

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

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

var currentPos = obj.getCurrentGridPos();

然后使用本地缓存的值:

if (obj.gridPos == currentPos) {

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

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

于 2012-07-15T17:50:42.420 回答
0

简短的回答是设置一个current position对象并对其自身进行检查,因为如果每次调用getCurrentGridPos().

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

currentGridPos使用RequestAnimationFramex y z设置并在更新之前检查其当前位置似乎是最佳选择,这样您就可以触发changedPosition类型事件。

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每次迭代不会多次调用。

于 2012-07-15T17:02:29.420 回答