Chrome中的画布性能变化

eri*_*sti 5 javascript performance google-chrome html5-canvas

我正在制作动画库,每隔一段时间就会进行一次基准测试,以查看某些功能带来的收益或损失。最近,我遇到了一些让我感到困惑的事情,也许有更多知识的人可以为我提供帮助。

之前的表现:

  • 铬:〜4460个精灵@ 30fps
  • Safari:约3017个精灵@ 30fps
  • FireFox:〜1273个精灵@ 30fps
  • iPhone 4S:〜450 @ 30fps

现在的性能:

  • Chrome:约3000个精灵@ 30fps
  • Safari:约2950个精灵@ 30fps
  • FireFox:约1900个精灵@ 30fps(在垃圾回收变得过于分散注意力之前)
  • iPhone 4S:〜635 @ 30fps

因此,您可以看到,Chrome在性能上大受打击,而其他所有浏览器在这段时间内似乎都变得更好。我注意到的最大问题是答案,那就是Chrome中的CPU使用率似乎已被降低(我发誓我可以提高到90%之前,现在最高达到60%)。大部分的CPU都用于该drawImage()调用,但我不确定我可以做些什么来优化它。

如果仅是Chrome现在限制我的CPU使用率的问题,那很好。

任何见识将不胜感激...

_s.Sprite.prototype.drawBasic = function() {
    var s = this.ctx;
    if(s.globalAlpha!=this._alpha) s.globalAlpha = this._alpha;

    var width = this.width;
    var height = this.height;
    var x = this._x;
    var y = this._y;

    if (_s.snapToPixel) {
        x = this._x + (this._x < 0 ? -1 : 0) | 0;
        y = this._y + (this._y < 0 ? -1 : 0) | 0;
        height = height + (height < 0 ? -1 : 0) | 0;
        height = height + (height < 0 ? -1 : 0) | 0;
    }


    var frame = this.sequence[this.frame] || 0;
    var sheetY = frame + (frame < 0 ? -1 : 0) | 0;
    var sheetX = (frame - sheetY) * this.spriteSheetX || 0;

    s.drawImage(this.bitmap.image, this.bitmap.frameRect.x2 * sheetX, this.bitmap.frameRect.y2 * sheetY, this.bitmap.frameRect.x2, this.bitmap.frameRect.y2, x - (width * this._scaleX) * this.anchorX, y - (height * this._scaleX) * this.anchorY, width * this._scaleX, height * this._scaleY);
    this.updateFrame();

};
Run Code Online (Sandbox Code Playgroud)

更新

因此,我下载了旧版本的Chrome(25.0.1364.5),并运行了基准测试: 之前

然后,我重新运行了最新版本的Chrome: 后

显然,Chrome已更改。是故意的吗?我不知道。您可以看到,在旧版本的Chrome中,我实际上比原来的4460有了更高的性能(+〜400,我的优化必须已经奏效),但是您也可以看到它使我能够在100%的CPU使用率上徘徊。2x cpu几乎是2x屏幕上的对象。

eri*_*sti 1

更新

setInterval没有这个问题。仅发生在requestAnimationFrame. 这终于有意义了。requestAnimationFrame已经将速度限制为 60fps,我不知道,而且似乎找不到任何信息,Chrome(其他?)将其限制为 30 (60/2),然后是 20 (60/3),可能15(60/4)...这使其与 60hz 保持同步,因此您永远不会得到看起来很奇怪的 40fps,因为它与屏幕刷新率不同步。

这解释了很多。我真的很享受这为我们带来的 CPU 节省。

更新

一个没有我的任何代码的例子... http://www.goodboydigital.com/pixijs/canvas/bunnymark/如果你在 Chrome 中运行这个...你会看到它从 ~60fps 直接跳到 30fps 的点。你可以继续添加更多的兔子,pixy 可以处理它......Chrome 正在限制 fps。这不是 Chrome 过去的行为方式。


所以我知道这是怎么回事了。这并不是说性能发生了变化,我仍然可以以 30 fps 在屏幕上显示 4800 个对象。改变的似乎是 Chrome 尝试优化最终用户体验的方式。它实际上将速度从 60fps 降低到约 30fps(根据开发工具为 29.9fps),这会导致if(fps>=30)返回 false:

    stage.onEnterFrame=function(fps){  // fps = the current system fps
        if(fps>=30){  // add astroids until we are less than 30fps
            stage.addChild(new Asteroid());
        }
    }
Run Code Online (Sandbox Code Playgroud)

由于某种原因,在 2800 个对象左右,Chrome 会降低至 30fps,而不是尝试尽可能快地运行...因此,如果我以 4800 个对象开始基准测试,它会保持在非常一致的 29.9fps。

帧率表

(您可以在这里看到它要么是 60fps 要么是 29.9fps,没有真正的中间值,唯一改变的是它切换的频率)

这是用于阶段计时的代码......

_s.Stage.prototype.updateFPS = function() {
    var then = this.ctx.then;
    var now = this.ctx.now = Date.now();
    var delta = now - then;
    this.ctx.then = now;
    this.ctx.frameRatio = 60 / (1000 / delta);
};
Run Code Online (Sandbox Code Playgroud)

希望这对其他人有帮助。