Jump to content

Gameloop and accuracy timer, feature/fix that was working, but not anymore


hashi
 Share

Recommended Posts

I've implemented `Timer` class for high accuracy timing (for example for update logic/game-loop, sending ping each 15 seconds by WebRTC etc.)

setTimeout/setInterval fires once per second when tab is inactive, so how to gain accuracy timing?

We could set up `setTimeout/setInterval` in WebWorker, because in WebWorkers when tab is inactive, `setTimeout/setInterval` still fires with it's own interval/delay.

We could then send message `postmessage/onmessage` from WebWorker to Main Thread on each `setTimeout/setInterval` fire calls as a tick.

For some time this idea was working and was brilliant, but when I'm looking now (latest chrome version) this isn't working anymore because of `postmessage`, now `postmessage` delivers event with delay when tab is inactive..

Looks like Chrome Dev Team noticed this feautre, and they've fixed it.. but it wasn't a bug? gaah.. or maybe I have something wrong in the code:

https://jsfiddle.net/mfzmotb1/16/

    Timer = function Timer(callback, interval) {
        var id = Timer.prototype.__idCounter++;
    
        Timer.prototype.__hash[id] = callback;
    
        this.started = false;
    
        this.package = JSON.stringify({
            id: id,
            interval: interval
        });
    }
    
    Timer.prototype.__workerScript = function() {
        var __hash = {};
    
        onmessage = function(ev) {
            var data = JSON.parse(ev.data);
    
            if ( __hash[data.id] === undefined ) {
                __hash[data.id] = {
                    id: data.id,
                    lastTime: performance.now(),
                    interval: data.interval,
                    step: 0
                }
            }
            else delete __hash[data.id];
        }
    
        function loop(start) {
            if ( !start ) for ( var id in __hash ) step(__hash[id]);
    
            setTimeout(loop, 0);
        }
    
        loop(true);
    
        function step(unit) {
            while ( performance.now() - unit.lastTime >= unit.interval ) {
                unit.lastTime += unit.interval;
                unit.step++;
                var now = Date.now();
                console.log("ww", unit.step, "-", now/1000);
                postMessage(JSON.stringify({id: unit.id, time: now, step: unit.step}));
            }
        }
    }
    
    Timer.prototype.__idCounter = 0;
    Timer.prototype.__hash = {};
    
    Timer.prototype.__worker = new Worker(URL.createObjectURL(new Blob(['('+Timer.prototype.__workerScript.toString()+')()'], {type: 'application/javascript'})));
    
    Timer.prototype.__worker.onmessage = function(ev) {
        var data = JSON.parse(ev.data);
        Timer.prototype.__hash[data.id](data.time, data.step);
    }
    
    Timer.prototype.start = function(){
        if ( !this.started ) {
            Timer.prototype.__worker.postMessage(this.package);
            this.started = true;
        }
    }
    
    Timer.prototype.stop = function(){
        if ( this.started ) {
            Timer.prototype.__worker.postMessage(this.package);
            this.started = false;
        }
    }
    
    var timer = new Timer(function(wwTime, step) {
        var now = Date.now();
        console.log("m_", step, "-", wwTime/1000, now/1000, (now-wwTime)/1000);
    }, 100);
    
    console.log("starting in 2sec, so you have time to switch tabs");
    
    setTimeout(function() {
        timer.start();
    }, 2000);

Basically this code produce new class called `Timer`, there is WebWorker based on one function body `Timer.prototype.__workerScript` <- this fn's body happens in WebWorker.

One WebWorker handles all instances of Timer, each instance is for one timer.

Any ideas how to fix it? Here goes output:

Some tips:

    ww - console.log called from webworker
    m_ - console.log called from main thread
    
    1,2,3 - number of timer step

Tab Active:

    starting in 2sec
    ww 1 - 1485111848.697 //webworker tick time in seconds
    m_ 1 - 1485111848.697 1485111848.707 0.01 //webworker tick time, main thread tick time, diff
    ww 2 - 1485111848.798
    m_ 2 - 1485111848.798 1485111848.799 0.001
    ww 3 - 1485111848.898
    m_ 3 - 1485111848.898 1485111848.898 0
    ...

Tab Inactive:

    starting in 2sec
    ww 1 - 1485110821.95 //webworker tick time in seconds
    ww 2 - 1485110822.049
    ww 3 - 1485110822.149
    m_ 1 - 1485110821.95 1485110822.169 0.219 //webworker tick time, main thread tick time, diff
    m_ 2 - 1485110822.049 1485110822.17 0.121
    m_ 3 - 1485110822.149 1485110822.171 0.022
    ...

 

Do you know any ideas for measuring time for html5 gaming without throttle?

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...