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). ако извадя долния цикъл while, броячът на FPS ще седи щастливо на 30 кадъра в секунда. Въпреки това, ако го оставя вътре, FPS броячът полудява. стига до 200FPS 300FPS, след което внезапно отива -200FPS -10FPS 0.01FPS. Напълно е извън стената. Цикълът 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 само малко по малко във всеки цикъл). Въпреки това открих проблема и той беше свързан с начина, по който генерирах своя брояч на Frame Rate. - person Simon Willan; 06.06.2012
comment
Вашият код по-горе обаче е по-добър от този, който имах, така че направих това вместо това! - person Simon Willan; 06.06.2012