requestAnimationFrame [now] vs performance.now() time discrepancy - javascript

Assumptions: rAF now time is calculated at the time the set of callbacks are all triggered. Therefore any blocking that happens before the first callback of that frame is called doesn't affect the rAF now and it's accurate--at least for that first callback.
Any performance.now() measurements made before a rAF set is triggered should be earlier than rAF now.
Test: Record before (a baseline time before anything happens). Set the next rAF. Compare rAF now and actual performance.now() to before to see how different they are.
Expected results:
var before = performance.now(), frames = ["with blocking", "with no blocking"], calls = 0;
requestAnimationFrame(function frame(rAFnow) {
var actual = performance.now();
console.log("frame " + (calls + 1) + " " + frames[calls] + ":");
console.log("before frame -> rAF now: " + (rAFnow - before));
console.log("before frame -> rAF actual: " + (actual - before));
if (++calls < frames.length) { before = actual; requestAnimationFrame(frame); }
});
// blocking
for (var i = 0, l = 0; i < 10000000; i++) {
l += i;
}
Observations: When there is blocking before the frame starts, the rAF now time is at times incorrect, even for that first frame. Sometimes the first frame's now is actually an earlier time than the recorded before time.
Whether there is blocking happening before the frame or not, every so often the in-frame time rAFnow will be earlier than the pre-frame time before--even when I setup the rAF after I take my first measurement. This can also happen without any blocking whatsoever, though this is rarer.
(I get a timing error on the first blocking frame most of the time. Getting an issue on the others is rarer, but does happen occasionally if you try running it a few times.)
With more extensive testing, I've found bad times with blocking prior to callback: 1% from 100 frames, no blocking: 0.21645021645021645% from ~400 frames, seemingly caused by opening a window or some other potentially CPU-intensive action by the user.
So it's fairly rare, but the problem is this shouldn't happen at all. If you want to do useful things with them, simulating time, animation, etc., then you need those times to make sense.
I've taken into account what people have said, but maybe I am still not understanding how things work. If this is all per-spec, I'd love some psuedo-code to solidify it in my mind.
And more importantly, if anyone has any suggestions for how I could get around these issues, that would be awesome. The only thing I can think of is taking my own performance.now() measurement every frame and using that--but it seems a bit wasteful, having it effectively run twice every frame, on top of any triggered events and so on.

The timestamp passed in to the requestAnimationFrame() callback is the time of the beginning of the animation frame. Multiple callbacks being invoked during the same frame all receive the same timestamp. Thus, it would be really weird if performance.now() returned a time before the parameter value, but not really weird for it to be after that.
Here's the relevant specification:
When the user agent is to run the animation frame callbacks for a Document document with a timestamp now, it must run the following steps:
If the value returned by the document object’s hidden attribute is true, abort these steps. [PAGE-VISIBILITY]
Let callbacks be a list of the entries in document’s list of animation frame callbacks, in the order in which they were added to the list.
Set document’s list of animation frame callbacks to the empty list.
For each entry in callbacks, in order: invoke the Web IDL callback function, passing now as the only argument, and if an exception is thrown, report the exception.
So you've registered a callback (let's say just one) for the next animation frame. Tick tick tick, BOOM, time for that animation frame to happen:
The JavaScript runtime makes a note of the time and labels that now.
The runtime makes a temporary copy of the list of registered animation frame callbacks, and clears the actual list (so that they're not accidentally invoked if things take so long that the next animation frame comes around).
The list has just one thing in it: your callback. The system invokes that with now as the parameter.
Your callback starts running. Maybe it's never been run before, so the JavaScript optimizer may need to do some work. Or maybe the operating system switches threads to some other system process, like starting up a disk buffer flush or handling some network traffic, or any of dozens of other things.
Oh right, your callback. The browser gets the CPU again and your callback code starts running.
Your code calls performance.now() and compares it to the now value passed in as a parameter.
Because a brief but non-ignorable amount of time may pass between step 1 and step 6, the return value from performance.now() may indicate that a couple of microseconds, or even more than a couple, have elapsed. That is perfectly normal behavior.

I encountered the same issue on chrome, where calls to performance.now () would return a higher value than the now value passed into subsequent callbacks made by window.requestAnimationFrame ()
My workaround was to set the before using the now passed to the callback in the first window.requestAnimationFrame () rather than performance.now (). It seems that using only one of the two functions to measure time guarantees progressing values.
I hope this helps anyone else suffering through this bug.

Related

time remainder of setInterval JavaScript

I want to be able to run code on the condition that there is time left on a setInterval.
let car = setInterval(function() {
// stuff
}, 2000);
let vehicle = setInterval(function() {
train()
}, 1000);
function train() {
// stuff
// and if car has time left, do this stuff too.
}
At the last line of the train function, I want to check the car's time remaining but don't understand how to go about such a concept.
I guess knowing the exact time left or simply that there is time left is the same to me so which ever is easier.
Remember that timers are potentially quite imprecise, and that setInterval's rules are...interesting...if your handler runs past when the next interval was meant to start. So important to keep in mind.
But if your goal is to know how long it's been since the start of the call to the timer vs when the timer is going to be set to fire again, it's a matter of remembering when you started
var start = Date.now();
...and then later checking how long it's been relative to the interval. For instance:
if (Date.now() - start >= 1900) {
// It's been at least 1900ms since the start of the `vehicle` call,
// so based on a 2000ms interval, in theory you have only 100ms left
}
But, again, note that timers can be quite imprecise if other things are keeping the UI thread busy.
This is not going to be possible. Timers are actually executed outside of the JavaScript runtime and the time specified in them is never a precise measurement - - it's actually the minimum time that the timer could be expected to run. The actual amount of time depends on how busy the JavaScript runtime is and if the runtime is idle at the timer's timeout, the timer's callback function can be run.
So, essentially, you'd have to calculate how much longer the JavaScript execution stack will need in order to become idle, which you can't do because in order to get that time measurement, you have to execute the remaining code. So, you can't get the answer until there's no time left.
But, based on your code, it seems that you could just set a simple "flag" variable that gets set when car runs. So, inside train you can check to see if that flag has been set yet and if not, run the train code and then reset the flag.

How to sleep a certain amount of seconds in the Phaser-Framework

In my game i'm trying to make a variable go up gradually, so i need to be able to sleep a certain amount of time before I increment the variable again.
1) Use a timer. This will allow you to execute one off delayed events, or execute that function call repeatedly.
An example, as the phaser website basically gives you examples of everything if you search for it,
http://phaser.io/examples/v2/time/basic-timed-event
Also, from the docs
http://phaser.io/docs/2.4.8/Phaser.Timer.html
Should you need to repeat, note the function "loop" (I would post the link, but i don't have enough reputation yet).
2) The alternative is simply to tie in to Phaser's game tick. Within your state (if this is where you are executing you variable incrementation), create an update function (this will be called every game update). You can access time since last update.
Look up the class Phaser.Timer (again, i cannot post the link).
See the properties elapsed and elapsedMS. You could use this to manually track time elapsed since your last incremental event (behind the scenes, this is basically what phaser tweens or timed events are doing).
eg:
var timeSinceLastIncrement = 0;
function update()
{
// Update the variable that tracks total time elapsed
timeSinceLastIncrement += game.time.elapsed;
if (timeSinceLastIncrement >= 10) // eg, update every 10 seconds
{
timeSinceLastIncreemnt = 0;
// Do your timed code here.
}
}
Note, that option 1 is cleaner, and likely to be the preferred solution. I present option 2 simply to suggest how this can be done manually (and in fact, how it is generally done in frameworks like phaser behind the scenes).

Javascript - run time priority and queue

if i do:
setTimeout(function(){ alert('antani'); },400);
setTimeout(function(){ alert('supercazzola'); },400);
why does this script generates queue between these two timeouts?
Shouldn't they alerted in same moment?
as i can see testing it out, first, the first alert is executed, then the second.
Background
JavaScript has only the one thread in which the interpreter is running. This means that events are never processed at the same time. When you set a timeout you actually subscribe to some internal event of the browser that fires each time browser is in the idle mode (when not busy with rendering, parsing or executing some script, etc.). The handlers of this event as well as time they were scheduled are posted to the queue according to the order setTimeout appeared in the script. Each time this internal event is fired, the browser checks each handler and decides whether to execute and remove it from the queue or to skip it.
Same Time
When you schedule the tasks one after another with the same estimation time
setTimeout(function(){ $('.element').hide(); },400);
setTimeout(function(){ $('.element').show(); },400);
the .element will be first hidden and then shown. Note that it does not mean that the browser will render the change to .element after it's hidden. Most browsers will only render after the script has finished executing.
Different Time
When you schedule tasks with different estimation times:
setTimeout(function(){ $('.element').hide(); },401);
setTimeout(function(){ $('.element').show(); },400);
the result may be unpredictable. The following cases may occur:
more or equal to 400 and less than 401 milliseconds have passed and browser is starting to process event handlers. In this case .element will first be shown and then hidden. Note that there may be other setTimeouts scheduled to be executed after 400 milliseconds and they will run prior to the hide .element.
browser was busy for 401 milliseconds or more before it first starts to process event handlers. In this case most likely (depending on browser implementation) the .element will first be hidden and then shown, despite the fact that according to estimation time it should be vice versa!
Regarding your question: is it the same to set timeouts with the same time or some positive delta the answer is NO. It is not the same, when you set timeouts with delta there is always a possibility that another event or timeout will be processed between them.
Please read: http://ejohn.org/blog/how-javascript-timers-work/
Here's a similar example:
function a(){
var num = 5;
console.log( ++num );
setTimeout( a, 100 );
};
setTimeout(a,2000);
In chronological order:
you are defining function a without calling it
you are scheduling a to be invoked after two seconds: setTimeout(a,2000)
it is called
when it is called, it schedules itself for invocation after 100 milliseconds
Your code basically sleeps for 2 seconds and then executes a with 100 millisecond pauses[*].
However judging by your context you are asking what is the priority in the following situation:
setTimeout(a, 2000);
setTimeout(b, 100);
Well, most likely b will be called first (assuming there is no unpredictable pause between first and second line, e.g. due to overall OS performance problem).
If you use the same timeouts:
setTimeout(a, 100);
setTimeout(b, 100);
a will most likely be called first. However I don't think this is guaranteed and depends on the JS engine (whether it uses a strict FIFO list for upcoming events, what is the internal clock resolution, etc.)

How can I make my setTimout functions run at the same speed?

Preface: I have a demo of the problem on my personal site (I hope this is ok. If not, I can try to set it up on jsfiddle). I'm intending this question to be a little fun, while also trying to understand the time functions take in javascript.
I'm incrementing the value of progress bars on a timeout. Ideally (if functions run instantaneously) they should fill at the same speed, but in the real world, they do not. The code is this:
function setProgress(bar, myPer) {
bar.progressbar({ value: myPer })
.children('.ui-progressbar-value')
.html(myPer.toPrecision(3) + '%')
.attr('align', 'center');
myPer++;
if(myPer == 100) { myPer = 0; }
}
function moveProgress(bar, myPer, inc, delay){
setProgress(bar, myPer);
if(myPer >= 100) { myPer = 0; }
setTimeout(function() { moveProgress(bar, myPer+inc, inc, delay); }, delay);
}
$(function() {
moveProgress($(".progressBar#bar1"), 0, 1, 500);
moveProgress($(".progressBar#bar2"), 0, 1, 500);
moveProgress($(".progressBar#bar3"), 0, .1, 50);
moveProgress($(".progressBar#bar4"), 0, .01, 5);
});
Naively, one would think should all run (fill the progress bar) at the same speed.
However, in the first two bars, (if we call "setting the progress bar" a single operation) I'm performing one operation every 500 ms for a total of 500 operations to fill the bar; in the third, I'm performing one operation every 50ms for a total of 5,000 operations to fill the bar; in the fourth, I'm performing one operation every 5ms for a total of 50,000 operations to fill the bar.
What part of my code is takes the longest, causes these speed differences, and could be altered in order to make them appear to function in the way that they do (the fourth bar gets smaller increments), but also run at the same speed?
The biggest problem with using setTimeout for things like this is that your code execution happens between timeouts and is not accounted for in the value sent to setTimeout. If your delay is 5 ms and your code takes 5 ms to execute, you're essentially doubling your time.
Another factor is that once your timeout fires, if another piece of code is already executing, it will have to wait for that to finish, delaying execution.
This is very similar to problems people have when trying to use setTimeout for a clock or stopwatch. The solution is to compare the current time with the time that the program started and calculate the time based on that. You could do something similar. Check how long it has been since you started and set the % based on that.
What causes the speed difference two things: first is the fact that you executing more code to fill the bottom bar (as you allude to in the 2nd to last paragraph). Also, every time you set a timeout, your browser queues it up... the actual delay may be longer than what you specify, depending on how much is in the queue (see MDN on window.setTimeout).
Love the question, i don't have a very precise answer but here are my 2 cents:
Javascript is a very fast language that deals very well with it's event loop and therefore eats setTimeouts and setIntervals for breakfast.
There are limits though, and they depend on a large number of factors, such as browser and computer speed, quantity of functions you have on the event loop, complexity of the code to execute and timeout values...
In this case, i think it's obvious that if you try to execute one function every 500ms, it is going to behave a lot better than executing it every 50ms, therefore a lot better than every 5ms. If you take into account that you are running them all on top of each other, you can predict that the performance will not be optimal.
You can try this exercise:
take the 500ms one, and run it alone. mark the total time it took to fill the bar (right here you will see that it's going to take a little longer than predicted).
try executing two 500ms timeouts at the same time, and see that the total time just got a bit longer.
If you add the 50ms to it, and then the 5ms one, you will see that you will lose performance everytime...

Understanding how alert() impacts browser event loop

I'm considering adding an alert() to our Javascript utility assert function.
We're an ajax-heavy application, and the way our framework (Ext) implements ajax by polling for the ajax response with setInterval instead of waiting for readystate==4, causes all of our ajax callbacks to execute in a setInterval stack context -- and an exception/assert blowing out of it usually fails silently.
How does a low-level alert() impact the browser event loop? The messagebox by definition must allow the win32 event loop to pump (to respond to the mbox button). Does that mean other browser events, like future setIntervals generated by our framework, resize events, etc, are going to fire? Can this cause trouble for me?
IIRC: you can use Firefox2 and Firefox3.5 to see the difference I'm talking about.
alert('1');
setTimeout(function(){alert('2');}, 10);
alert('3');
Firefox3.5 shows 1-3-2. Firefox2[1] shows 1-2&3 (2 and 3 stacked on top of each other simultaneously). We can replicate 1-2&3 in IE8 with a win32 mbox launched from ActiveX as well, instead of an alert, which wreaked havoc on us back in the day, and I want to make sure we don't go down that path again.
Can anyone point me to specific low level resources that explain this behavior, what the expected behavior is here, and what exactly is going on at a low level, including why the behavior changed across Firefox versions?
[1] you can replicate this on Spoon.net which I can't get working right now. I just reproduced it in a VM with Firefox 2.0.0.20.
First, timers in javascript are not very precise. Intervals smaller than 30ms might be considered all the same, and implementations vary. Don't rely on any implicit ordering.
An alert() will always halt the event loop. If an event or timer fires during the alert, they will be queued and called after the event loop resumes (the alert box is closed).
Take this example:
var hello = document.getElementById('hello')
setTimeout(function(){
hello.style.backgroundColor = 'lime'
}, 5000)
alert('Stop!')
setTimeout(function(){
hello.innerHTML = 'collaborate'
}, 20)
setTimeout(function(){
hello.innerHTML = 'listen'
}, 1000)
There are two possible outcomes:
You close the alert box in under 5 seconds. The two timers that follow will be set and fire at specified intervals. You can see that the event loop is halted because regardless of how long you wait to close the alert, "listen" will always take 1s to execute.
You take longer than 5 seconds to close the alert. The first interval (bgColor) will have passed, so it executes immediately, followed by the two timers being set and called.
http://jsbin.com/iheyi4/edit
As for intervals, while the event loop is stopped it also "stops time", so in this case:
i = 0
setInterval(function(){
document.getElementById('n').innerHTML = ++i
}, 1000)
setTimeout(function(){
alert('stop')
}, 5500)
Regardless of how long you take to close the alert, the next number will always be 6 - the setInterval won't fire multiple times.
http://jsbin.com/urizo6/edit
I haven't been able to replicate the 1-2&3 case, but here is a fiddle that may help you debug what is going on in the different browsers.

Categories

Resources