为什么在画布上填充矩形会导致性能逐渐下降?

3
我目前正在开发一个利用<canvas>元素的HTML5游戏。随着时间的推移,程序性能神秘地降低,希望您可以解释一下这种行为。
我已经追踪到问题出现在绘制每个帧的背景的函数中。简而言之,它看起来是这样的:
function paintBackground() {
  ctx.rect(0, 0, canvas.width, canvas.height)
  ctx.fillStyle = "black"
  ctx.fill()
}

我还设置了一个JSFiddle来表示这种情况。

这段代码有趣的地方在于,当测量时,它的效率会逐渐降低几个数量级。以JSFiddle为例,它开始时函数只需要不到一毫秒就能完成。大约2-3秒后,它报告现在需要约1毫秒。10秒后,平均值在2-3毫秒之间。一分钟内平均值约为6-7毫秒,当我让它运行约5分钟时,它高达13-14毫秒。这比开始时慢了数百倍,而且没有任何变化!我已经在IE 11和Firefox 35.0.1中测试了相同的代码。两者都显示出相同的退化,但在Firefox中似乎稍微下降得更快。

现在,我不是一个过分关注微观优化的人,但我的目标是达到稳定的60FPS,这意味着我只有约16.67毫秒用于渲染和更新,而仅仅通过渲染背景,我就已经逐渐失去了其中一半的时间!我还担心这可能会变得越来越糟糕,谁知道性能会变得多么糟糕;可能导致我的游戏无法玩耍。
据我所知,这是造成性能下降的唯一因素,原因如下:1)游戏代码的其余部分都运行顺畅,包括渲染组成一个级别的所有图块(每帧375+个图块),2)即使在提供的JSFiddle中,也会出现这种行为,其中除了矩形填充之外什么也没有。
任何关于这种行为的解释或建议都将非常有启发性!
附言:我知道这听起来很愚蠢,但还有其他人遇到过这种情况吗?还是只有我?我应该指出,我的CPU速度足够慢(1.4ghz双核),以至于这很明显。

2
已确认在IE11和Firefox中降级,但在Chrome中没有。 - Rick Hitchcock
1个回答

4
rect()命令会添加到路径并累加,因此每次调用fill()时,所有先前的矩形都将被填充。
有两种解决方法:
function paintBackground() {
  ctx.beginPath(); // RESET path here
  ctx.rect(0, 0, canvas.width, canvas.height);
  ctx.fillStyle = "black";
  ctx.fill();
}

或者直接填写而不使用路径:

function paintBackground() {
  ctx.fillStyle = "black";
  ctx.fillRect(0, 0, canvas.width, canvas.height);
}

使用requestAnimationFrame可以实现更好的动画效果。

修改后的fiddle

PS:请不要忘记分号。


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