Javascript setTimeout и частота кадров

Кажется, у меня есть неожиданные результаты со счетчиком частоты кадров в javascript. До недавнего времени счетчик был в порядке, и я запускал свое маленькое js-приложение со скоростью 30 кадров в секунду.

Он использует setTimeout() (с корректировкой времени для противодействия «отставанию» системы).

window.requestAnimFrame = (function() 
{
    return function (callback) {
        time += FPS;
        Heartbeat._eTime = (new Date().getTime() - Heartbeat._start);
        var diff = Heartbeat._eTime - time;

        Heartbeat._delta = FPS - diff;
        Heartbeat._deltaS = Heartbeat._delta / 1000;

        window.setTimeout(callback, FPS - diff);
    };
})();

Heartbeat — это просто объект, который содержит информацию о частоте кадров.

*Вот моя проблема: *

_MainLoopHandler: function () {

    timer = new Date().getTime();
    counter = timer;

    while (this._messages.length > 0 && (counter - timer) < 5)
    {
        // process messages from _messages array
    }

    counter = new Date().getTime();
    // THE ABOVE IS HAPPY AT 30 FPS


    while ((counter - timer) < 6) {
        1 + 1;
    }
    // THE ABOVE WHILE IS VERY UNHAPPY :(

}

Таким образом, приведенный выше блок кода — это функция, которая вызывается из setTimeout каждые 33,33 миллисекунды (30 кадров в секунду). если я возьму нижнюю часть во время цикла, счетчик FPS будет счастливо сидеть на 30 кадрах в секунду. Однако, если я оставлю его включенным, счетчик FPS сойдет с ума. он поднимается до 200 кадров в секунду, 300 кадров в секунду, а затем внезапно становится -200 кадров в секунду -10 кадров в секунду 0,01 кадра в секунду. Это полностью от стены. Цикл while будет выполняться только 10 раз за «кадр».

Также обратите внимание, что жестко закодированные значения 5 и 6 — это просто проверка того, прошло ли 5 ​​или 6 миллисекунд при обработке циклов (для балансировки нагрузки).

Это просто javascript не может обработать объем информации или у кого-то еще была похожая проблема.

Спасибо!


person Simon Willan    schedule 25.05.2012    source источник


Ответы (1)


Я действительно не знаю, что происходит, но я думаю, что вы должны использовать локальные переменные, чтобы контролировать свое время, постоянно переоценивать counter и обрабатывать по 1 сообщению за раз. Кроме того, я не очень понимаю этот последний цикл (я также переименовал переменные):

_MainLoopHandler: function () {

  var start = new Date().getTime();
  var current;

  do {
    if (this._messages.length === 0) break;
    // process 1 message
    current = new Date().getTime();
  } while (current - start < 5);

}

Вы также можете инкапсулировать проблему время в объект (не показан), чтобы упростить код:

_MainLoopHandler: function () {

  var timing = new Timing();

  do {
    if (this._messages.length === 0) break;
    // process 1 message
  } while (timing.elapsed() < 5);

}
person Jordão    schedule 03.06.2012
comment
Последний цикл был просто примером выполнения чего-либо. В моем обновленном коде он фактически обрабатывает потоковую передачу SVG узел за узлом (поэтому я создаю SVG только побитно в каждом цикле). Тем не менее, я обнаружил проблему, и она была связана с тем, как я генерировал свой счетчик частоты кадров. - person Simon Willan; 06.06.2012
comment
Однако ваш код выше лучше, чем у меня, поэтому вместо этого я сделал это! - person Simon Willan; 06.06.2012