Are There Any Standards for Mobile Device Web Browsers in Terms of Thread Sleeping

Are there any standards for mobile device web browsers in terms of thread sleeping?

No JavaScript framework can stop the execution or change the behaviour of the underlying JS engine. They will not be able to influence setTimeout.

Yet, the behaviour is standardisized in the current HTML5 draft on the WindowTimers interface (which does not mean it was implemented like that). There you will find the note:

This API does not guarantee that timers will run exactly on schedule. Delays due to CPU load, other tasks, etc, are to be expected.

and, even more explicit:

9) Optionally, wait a further user-agent defined length of time.

Note: This is intended to allow user agents to pad timeouts as needed to optimise the power usage of the device. For example, some processors have a low-power mode where the granularity of timers is reduced; on such platforms, user agents can slow timers down to fit this schedule instead of requiring the processor to use the more accurate mode with its associated higher power usage.

You can see such behaviour also on desktop browsers, which implement a minimum timeout of 4ms (read explanation on MDN). So, it is legitimate for every device/software/firmware to stop such execution if they only think it would be necessary.

You might also want to have a look at the WindowAnimationTiming draft.

And if you do use setInterval/setTimeout in animations/clocks/etc, always measure the really elapsed time with Date objects (e.g. via Date.now()).

setTimeout / setInterval mobile browser to calculate cpu efficiency

You can use console.time:

function someFunction(){
console.timeEnd('someFunction timer');
//this function's code goes here...
console.time('someFunction timer');
}

This will give you the time your function took to execute. Is this what you needed?

Or maybe this?

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

//your code
var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time);

when is the callback passed to setTimeout put on the message queue?

Is callback put on the message queue after 1000ms or is it put to the message queue immediately?

After 1000ms - that's when the timer runs out. If it was put on the message queue immediately, there would be no waiting before is run.

If it is put to the message queue after 1000ms, then does that mean that the 1000 does not mean that the callback will run in 1000, but instead it means that the callback may be run at a minimum only after 1000?

Yes, if the event loop is still busy with other tasks (especially long-running blocking code) at that time, it will have to wait for those to finish. The message queue is a queue, it is serviced one task after the other; no two callbacks are executed in parallel.

(Notice that setTimeout is allowed to lag arbitrarily anyway).

Timeout/Interval is CPU or browser based?

By default, setTimeout uses the system's internal timer, which has a granularity of 16.66...ms (a frequency of 60 Hz, aka 60 frames per second). Some browsers override this (which is actually really bad for the processor - although in the case of Internet Explorer it only does this if the computer is specifically set to "High Performance" mode, otherwise it uses the less harmful 60fps limit)

However, even if the setTimeout were perfectly accurate, it takes time to process the JavaScript within. As much as we'd like it to be, code is not truly realtime. This means that, even with a compeltely accurate 1,000ms timer, after a few thousand iterations you will start to notice a visible discrepency.

All in all, setTimeout (and by extension setInterval, which is basically just setTimeout with an automatic renewal) is unreliable. If you want reliability, you must use delta timing.

Delta timing is when you save the time at which you start the timer, and compare it to the time when the timer fires. A simple example is this:

var start = new Date().getTime();
setInterval(function() {
var now = new Date().getTime(), delta = now-start;
console.log("Timer fired after "+delta+"ms");
// chances are, you'll see numbers between 984 and 1016, unless your browser
// is a processor-killing, rainforest-destroying monster :p
// even then, you'll probably see some 999s and 1001s, depending on how
// busy your computer is with other tasks. Open a YouTube video, you'll see.
},1000);

This becomes even easier with the new requestAnimationFrame function. However, keep in mind that it's a new feature, and most browsers haven't adopted it without a vendor prefix. Internet Explorer is the only browser that I'm aware of that has. And people say that IE sucks!

Anyway, assuming you have a suitable polyfill, it would look like this:

var previous = new Date().getTime(); // or Date.now() if you're feeling brave...
// or are already excluding old browsers via canvas use
requestAnimationFrame(function(now) {
var loopit = arguments.callee, delta = now-previous;
previous = now;
console.log(delta); // should be around 16 or 17
requestAnimationFrame(loopit);
});

Seems like a lot of work for something that's basically just a glorified setTimeout, right?

Well, yes. But one thing I particularly like is that requestAnimationFrame will wait until a frame is actually being rendered. In particular, this means that if you are looking at a different tab, requestAnimationFrame will wait for you to come back. I use this to delay auto-updating AJAX requests, allowing the user to actually see the update then and there, rather than coming back and saying to themselves "now... has it updated? I don't know, I don't remember what it was before..." And instead they get to admire some neat transitions and come to you telling you how cool it is that it waits for you to come back before updating ;) When your users think something is cool, then that's really cool. (Protip: carousels are not cool - I know many people who would do well to learn this!)

Anyway, I've sort of rambled a bit. I don't know if I've answered your question, but I certainly hope that I've enlightened you some, and that you've found this interesting, if tangential.

Have fun!

Window.setTimeout(f, 0) waits a lot when browser (Chrome) idles

Found an answer in related question: this happens when tab is inactive, because timers in inactive tabs fire once a second, so waiting "overhead" is floating from 0 to 1 second.
Feels like not a real performance problem for users, but a real problem for our performance measurements...

Issue creating valid test case for promise rate limit function

setTimeout (which is internally used in Promise.delay) does not guarantee accurate timing, it only ensures that the callback is invoked not before the given timeout expires. The actual timing will depend on machine load, the speed of the event loop, and possibly anything else.

In fact, the Node.js docs only state that

The callback will likely not be invoked in precisely delay milliseconds. Node.js makes no guarantees about the exact timing of when callbacks will fire, nor of their ordering. The callback will be called as close as possible to the time specified.

What will happen in your tests is that Promise.delay(50) sometimes takes longer than 50ms (not by much, but still), and the difference to the following log can become less than 100ms when the next Promise.delay(50) is more on time.

You should be able to mitigate this effect if you simply log the invocation times of your example function immediately, not after the artificial delay of about 50ms:

const example = v => {
timeLog.push(new Date);
runCount++;
return Promise.delay(50, v)
};

To deal with the inaccuracy of the 100ms timeout itself, the easiest solution is to give it some leeway of maybe 5% (which makes 5ms in your case):

const invalidIntervals = filter(intervals, (interval) => interval < 100 * .95)
t.true(totalTime >= 400 * .95)

If you want to be absolutely sure that the delay is never too short, you can write your own function:

Promise.delayAtLeast = function(delay, value) {
const begin = Date.now()
return Promise.delay(delay, value).then(function checkTime(v) {
const duration = Date.now() - begin;
return duration < delay
? Promise.delay(delay - duration, v).then(checkTime);
: v;
});
};

and use that in promiseRateLimit.



Related Topics



Leave a reply



Submit