带有canvas的html5游戏,firefox上的性能问题(4)
目前我正在开发一个名为“tunnel 2”的js/canvas小游戏(我很确定这个游戏有一个众所周知的一年前版本,但我不知道)。您可以在这里尝试游戏。另外,我推荐 chrome。
所以,我在谷歌浏览器中开发,即使在我蹩脚的旧机器上,它也能正常工作。我的帧率约为 30 fps。在我同事的笔记本上,它的速度> 100 fps。到目前为止,一切都很好。 Safari 似乎也运作良好。
接下来我在 firefox 4 beta 10 上尝试了...但我只能得到约 10 fps。但 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();
是迄今为止最昂贵的函数,但在 chrome 上只需要几毫秒(实际上大约 5 毫秒)... 也可以在 Firefox 上。微不足道的 10fps 所需的时间远不及 >100ms!整个 loop()
调用也花费不了多少时间,在 Firefox 上花费的时间不到 10 毫秒!
如果您研究dt
,就会发现差异。它应该在 time-loop()-takes+5ms 超时左右(或浏览器最小超时值)。
但在 ff4 上,该值接近 180 毫秒,即下一个超时事件在 170 毫秒内触发,而不是 5 毫秒!如果你玩的时间长一点,单帧的时间会达到约 800 毫秒(当然是 gc),然后又回到 180 毫秒。
有人知道罪魁祸首是什么吗?
是GC的错吗?一方面,我不认为我创建了太多短暂的变量,嘿,每次 150 毫秒!?但当然可能是这样。有没有简单的方法来检查这个? chrome 分析器会记录 gc 时间(大约 0.10%),但 firebug 分析器不会。
同样有趣的是:启用 Firebug 后游戏运行速度更快(~5fps)。
添加。信息:使用 setInterval 而不是 setTimeout 不应该也不会改变任何内容。
currently i work on a little js/canvas game called "tunnel 2" (i'm pretty sure there's a well known year old version of this, but i know of none). you can try the game here. also, i'd recommend chrome.
so, i developed in google chrome, and it works fine, even on my crappy old machine. i get around ~30 fps. on my coworkers notebook it yields >100fps. so far, so good. safari seems to work well too.
next i tried it on firefox 4 beta 10 ... and i only get ~10 fps. but surely ff4 isn't that slow, right?
i started to investigate. here's my main loop:
// 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();
}
what i observed:
unsurprisingly, this.draw();
is by far the most expensive function, but it takes only some milliseconds (around 5, actually), on chrome ... and also on firefox. nowhere near the >100ms it would take for meager 10fps! the whole loop()
call takes not much more either, on firefox it takes less than 10ms!
the difference can be seen if you investigate dt
. it should be around time-loop()-takes+5ms timeout (or whatever the browser minimum timeout value is).
but on ff4 the value is closer to 180ms, aka the next timeout event fires in 170ms instead of 5ms! if you play a little longer, it goes up to ~800ms for a single frame (gc, for sure), then it's back to 180ms.
does anybody have an idea what the culprit could be?
is the GC to blame? on the one hand i don't think i create too many short lived variables, and hey, 150ms every time!? but of course it could be. is there an easy way to check this? the chrome profiler logs gc times (around 0.10%), but the firebug profiler doesn't.
also interesting: the game runs faster (~5fps) with firebug enabled.
add. info: using setInterval instead of setTimeout shouldn't and doesn't change anything.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
我可以确认它无法在 FF 3.6.13 OS X 上运行。
当我开发 Snake JS 时,我发现
setInterval
行为存在差异。您确实应该看看这个:我看到您没有使用
setInterval
,但也许它与setTimeout
类似?I can confirm it's not working on FF 3.6.13 OS X.
While I was developing Snake JS I found a difference in
setInterval
behavior. You should really have a look at this:I see you're not using
setInterval
, but maybe it's something similar withsetTimeout
?在处理 Firefox 6 及以下版本时,我构建和使用的一些高端画布应用程序遇到了重大问题。 Firefox 中存在许多涉及性能以及画布功能较差或完全不受支持的问题。他们确实在 Firefox 7 中进行了重大更新,改进了您可能注意到的许多问题。这有点烦人,我需要在一个巨大的基于 facebook 画布的应用程序上支持低至 ff4 的功能,而该应用程序在 6 及更低版本中运行得不太好。我做了很多事情来尝试解决与性能相关的问题,但大多数事情都很难找到解决方案。
I have had major issues with some higher end canvas applications I've built and used when having to deal with firefox 6 and under. There are many issues that involve performance and just poorly or completely unsupported canvas capabilities in firefox. They did make a huge update in firefox 7 that improves many of the issues that you are probably noticing. It's kind of annoying, i need to support down to ff4 on a huge facebook canvas-based app that doesnt quite work that great in 6 and lower. I've done so many things to try and hack around the performance related issues and it's really difficult to find solutions for most things.