使用Canvas的HTML5游戏在Firefox上存在性能问题(4)

3

目前我正在开发一个名为“隧道2”的小型js/canvas游戏(我相信已经有一个广为人知的版本,但我不知道)。你可以在这里尝试游戏。另外,我建议使用chrome浏览器。

所以,我在google chrome中开发,它运行良好,即使在我的旧机器上也是如此。我获得了约30帧每秒的效果。在我的同事笔记本电脑上,可以达到100多帧每秒。到目前为止,一切都很好。safari看起来也很不错。

接下来,我尝试了firefox 4 beta 10...然后我只能获得大约10帧每秒的效果。但是ff4肯定不会那么慢,对吧?

我开始进行调查。以下是我的主循环:

// starts the game loop
this.run = function () {
  this.draw();

  var
    t = this,
    timeLastTurn,
    timeThisTurn = (new Date()).getTime()-1;

  var loop = function () {
    timeLastTurn = timeThisTurn;
    timeThisTurn = (new Date()).getTime();

    // dt is the time difference between this turn and the last turn
    var dt = timeThisTurn - timeLastTurn;

    // player movement etc
    t.turn(dt);

    // draw game state
    var res = t.draw();

    // if there's no collision, game over
    if (!res.collision)
      t.setState(2);

    // actually, there's a browser dependent minimum timeout that
    // may vary. but even if it's more than 10ms - we don't care.
    // game should run at the same speed (though not as smooth)
    if (gameState == 1)
      timer = window.setTimeout(loop, 5);

    // just debug output
    debug = dt;
  }

  // start the main loop
  loop();
}

我观察到:

毫不意外,this.draw();是迄今为止最耗费时间的函数,但它只需要几毫秒(实际上大约是5毫秒),在Chrome上也是如此……在Firefox上也是如此。远远没有10fps所需的100毫秒!整个loop()调用所需的时间也不多,Firefox上不到10毫秒!

如果您调查dt,就可以看到差异。它应该约为time-loop()-takes+5ms timeout(或浏览器最小timeout值)。

但是在ff4上,该值更接近180毫秒,即下一个timeout事件在170毫秒而不是5毫秒后触发!如果您玩得更久一些,单帧的时间会增加到约800毫秒(肯定是gc),然后又回到了180毫秒。

有人有什么想法可以解决问题吗?

垃圾回收器是否有责任?一方面,我认为我没有创建太多短期变量,而且每次都要花费150毫秒吗?但当然可能是。有没有一种简单的方法来检查这个?Chrome分析器记录gc时间(约为0.10%),但Firebug分析器没有。

另外有趣的是,启用Firebug后游戏运行得更快(约5fps)。

附加信息:使用setInterval而不是setTimeout不应该也不会改变任何内容。


3
不错的上瘾游戏 - 尽管我玩了98.1秒后回到stackoverflow时感觉眼睛被刺瞎了,很疼… - Shadi Almosri
1
@Schnalle 火狐浏览器的bug:ctx.arc(75,75,50,0,Math.PI*2,true);,请查看第270行。.arc方法需要6个参数而不是5个。 - Raynos
@shadi:谢谢!是的,这个颜色方案太疯狂了。我会改变它的!
@raynos:是的,我试过了,但是我没能找到任何东西。感谢ctx.arc的bug(尽管没有那个也可以很好地工作)。
@fazo:那么在Chrome中播放它,你将获得超过100fps :)
- stefs
@tom tu:有趣。现在我只需要找到一个旧的MacBook Pro,这样我就可以在那里测试它 :) - stefs
@Schnalle 我也在我的iMac上测试了Firefox 3.6.13 - 第一次可以达到72fps,之后的播放速度为64-68fps(核心i5 iMac) - 完全正常运行 :) - Tom Tu
显示剩余3条评论
2个回答

0

我可以确认它在FF 3.6.13 OS X上不起作用。

当我开发Snake JS时,我发现setInterval的行为有所不同。您应该真正关注这一点:

var timer = setInterval(fn, 500)
// ...
timer = setInterval(fn, 500)
// Since I didn't use clearInterval() I now have two timers running in FF.

我看到你没有使用setInterval,但也许可以用类似的setTimeout来实现?


说实话,除了Chrome和FF4之外,我甚至没有尝试过其他浏览器。我看到有人在Safari上玩,而且运行良好。但是FF3?我怀疑它是否能够足够快地运行。 - stefs
关于多个setTimeout:我检查过了,那不是问题。 - stefs

0

我在构建和使用一些高端画布应用程序时,遇到了一些严重的问题,特别是在处理Firefox 6及以下版本时。有许多问题涉及性能和Firefox中不良或完全不支持的画布功能。他们在Firefox 7中进行了大规模更新,改善了您可能注意到的许多问题。这有点烦人,因为我需要支持一个基于Facebook画布的大型应用程序,该应用程序在6及以下版本中效果不佳。我已经尝试了许多方法来解决与性能相关的问题,但对于大多数事情,真的很难找到解决方案。


我不确定这完全是canvas的问题——可能是计时器或垃圾回收问题——只是你只能在本来应该很平滑的canvas动画中注意到它。渲染速度很快,但计时器事件触发太晚了。我应该将其转换为requestAnimationFrame并查看是否有任何差异,但这只是一个周末项目,现在并不重要。 - stefs
无论如何,在Firefox 6及以下版本中,性能肯定存在问题。我可以百分之百确认。 - jaredwilli

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接