2013-09-10 3 views
4

Я работаю над библиотекой анимации, и время от времени я запускаю тестовый тест, чтобы узнать, какая часть прибыли или убытка я получаю с определенными функциями. Недавно я столкнулся с чем-то, что меня совершенно озадачило, возможно, кто-то с большим количеством знаний может осветить это для меня.Изменение производительности холста в Chrome

Производительность До:

  • Chrome: ~ 4460 спрайты @ 30fps
  • Safari: ~ 2817 спрайты @ 30fps
  • FireFox: ~ 1273 спрайты @ 30fps
  • iPhone 4S: ~ 450 @ 30fps

Peformance Now:

  • Chrome: ~ 3000 спрайты @ 30fps
  • Safari: ~ 2950 спрайты @ 30fps
  • FireFox: ~ 1900 спрайты @ 30 кадров в секунду (до Garbage Collection становится слишком отвлекают)
  • iPhone 4S: ~ 635 @ 30fps

Итак, вы можете видеть, что Chrome сильно пострадал от производительности, в то время как каждый другой браузер, похоже, немного улучшился за это время. Самая большая вещь, которую я замечаю, и то, что я считаю, - это ответ, что использование ЦП, похоже, заглохло в Chrome (я клянусь, прежде чем я смогу подняться почти на 90%, теперь его максимальная около 60%). Большинство процессоров используется для вызова drawImage(), и я не уверен, что могу что-то сделать для его оптимизации.

Если это просто проблема, когда Chrome теперь ограничивает использование моего процессора, я в порядке.

Любое понимание было бы весьма признателен ...

_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(); 

}; 

UPDATE

Я скачал старую версию Chrome (25.0.1364.5), и побежал мой эталонный тест: Before

Затем я переработал в самой последней версии Chrome: After

Ясно, что Chrome изменился. Это было специально? Я не знаю. Вы можете видеть, что в старой версии Chrome я на самом деле получил больше производительности по сравнению с моими оригинальными 4460 (+ ~ 400, мои оптимизации, должно быть, сработали), но вы также можете увидеть, что это позволяет мне набирать 100% -ный процессор. 2x cpu почти 2x объект на экране.

+4

Это будет трудно ответить, не видя соответствующего кода. –

+0

1) если вы ищете возможности, поместите изображение внутри холста на 33%. 2) координаты экрана всегда будут> = 0, поэтому нет необходимости проверять знак. Если координата <0, то обрабатывайте отсечение правильно или не рисуйте, если вне экрана. 3) вы можете обойти ширину, высоту, указанную в последних аргументах drawImage, чтобы получить более высокую скорость. 4) вы можете захотеть кэшировать в холст масштабированную версию вашего изображения, чтобы, наконец, выполнить ничью 1: 1. – GameAlchemist

+1

Я предполагаю, что людям не хватает моего вопроса ... Я не пытаюсь добиться успеха с этим вопросом, для этого у меня есть всевозможные трюки. То, о чем я не знал, было то, как Chrome изменил свое поведение, чтобы в конечном итоге опуститься до 30 кадров в секунду. Я только включил код, потому что люди продолжают его просить. Пример без моего кода ... http://www.goodboydigital.com/pixijs/canvas/bunnymark/, если вы запустите это в Chrome ... вы увидите момент, когда он перескочит с ~ 60 кадров в секунду до 30 кадров в секунду. Это не то, как Chrome использует себя. – ericjbasti

ответ

1

Update

setInterval не вопрос. Только с requestAnimationFrame. Это, в конце концов, имеет такой смысл. requestAnimationFrame уже дросселирует вещи до 60 кадров в секунду, о чем я не знал, и, похоже, не могу найти информацию о том, что Chrome (другие?) дросселируйте его до 30 (60/2), а затем 20 (60/3) и, вероятно, 15 (60/4) ... это удерживает его в синхронизации с 60 Гц, поэтому вы никогда не получите 40 кадров в секунду, что выглядит странно, потому что его синхронизации с частотой обновления экрана.

Это объясняет многое. Я действительно наслаждаюсь экономией процессора, это дает нам.

Обновлено

Пример без какой-либо из моего кода ... http://www.goodboydigital.com/pixijs/canvas/bunnymark/, если вы запустите в Chrome ... вы увидите точку, когда он прыгает от ~ 60fps прямо в 30fps. Вы можете продолжать добавлять больше кроликов, pixy может справиться с этим ... Chrome регулирует fps. Это не то, как Chrome использует себя.


Итак, я понял, что происходит здесь. Дело не в том, что производительность изменилась, скажем, я могу получить 4800 объектов на экране со скоростью 30 кадров в секунду. Похоже, что изменилось то, как Chrome пытается оптимизировать работу конечных пользователей. Это на самом деле душит вещи вниз от 60fps до ~ 30 кадров в секунду (29.9fps согласно Дев инструментов), что вызывает if(fps>=30) вернуть ложь:

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

почему-то около 2800 объектов, Chrome дроссели до 30 кадров в секунду вместо того, чтобы пытаться идти как можно быстрее ... Так что, если я начну отсчет с 4800 объектов, он останется на уровне 29,9fps.

fps meter

(вы можете увидеть здесь, что его либо 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); 
}; 

Надеюсь, это поможет кому-то еще по дороге.

+0

Чувак, вы не должны блокировать игровые действия и анимацию в fps, но со временем. блокировка до fps даст вам переменную скорость. нехорошо! –

+0

@ Mike-O ...это бенчмарк ... все, что он хочет сделать, это добавить столько астероидов, сколько возможно, пока не достигнет 30 кадров в секунду. Я добавил в свой код времени, поэтому вы увидите, что вся система не зависит от частоты кадров. Тем не менее, вы все еще можете получить представление о FPS, посмотрев на дельту между 'now and then' ... сделайте некоторую математику, и у вас есть ваш FPS. – ericjbasti

+0

Метр Chrome fps - достаточно грубо - убийца производительности, следовательно, убийца fps. От 60 до 30 просто означает, что один кадр пропустить на дисплее 60 Гц. Вы не указали, используете ли вы метод renderAnimationFrame или setInterval. – GameAlchemist

Смежные вопросы