Precise timing on setTimeout function [duplicate] - javascript

This question already has answers here:
Is there a more accurate way to create a Javascript timer than setTimeout?
(16 answers)
Closed 9 years ago.
I need to reproduce an animation-like effect on the browser (mobile and desktop), this effect is just a procedural changes on the background color from black to white.
The timming is important, since a black background for a short time means "0" and a longer time means "1" (is like a binary Morse code). This information is interpreted by a light sensor in front of the screen. The sensor is very fast, and if we use a lower frequency we wont have problems with the screen (assuming a maximum refresh rate of 50Hz).
This is the script im using:
var i = 0;
var b0t = 100;
var b1t = 3.5 * b0t;
var wl = 100;
function pulses (){
bytes = "1001101010110101001000100";
bit = bytes[i];
i += 1;
document.body.style.backgroundColor = 'white';
document.body.style.color = 'white';
setTimeout(toblack, wl);
if(i <= bytes.length) {
if (bit == 1)
setTimeout(pulses, b1t + wl);
else
setTimeout(pulses, b0t + wl);
}
}
function toblack() {
document.body.style.backgroundColor = 'black';
document.body.style.color = 'black';
}
pulses ();
And a working demo (Do not open if you suffer any epileptic syndrome)
The problem is, 1 out of 20 the browser mess the timing, of course in the sensor side i have a tolerance range, a very tolerant range, but again the browser some times is out by several milliseconds, and this is no surprise, if your computer of cellphone is doing something in the background the performance of the browser is severely affected.
Is there a software solution for this? I was thinking using flash to do the flickering with more precision, but i really like my app to be accessible also from IOS. Or i can make a native app that for sure will be more precise than the browser, but then again, i will like to know if i can make it work on the browser.

the only thing i can suggest you to try is, forget about sestTimeout and try Date().getTime() it will give you a microsecond unix timestamp and you can try to query that and implement your own set timeout... i dont know if that will work, but you lost nothing trying.
take a look here http://www.sitepoint.com/creating-accurate-timers-in-javascript/
there are some examples.

Related

prevent javascript from pausing after switching browser tabs [duplicate]

This question already has answers here:
How can I make setInterval also work when a tab is inactive in Chrome?
(16 answers)
Closed 5 days ago.
I have a problem. I have a script that decreases the width of an element for 15 seconds. The script works normally, however when switching to another browser tab, the script pauses its execution, and only resumes when I return to the script tab again.
I looked all over the internet and I couldn't find anything that could solve this problem.
I want the user to be able to visit other tabs and for the script to continue decreasing the width of the file, based on the seconds that have been configured.
does anyone know if it's possible?
I looked all over the internet for a solution and I couldn't find it.
my code
var contagemInicial = document.querySelector('.seconds'),
life = document.querySelector('.life'),
time = contagemInicial.textContent,
[segundos, centesimos] = time.split(":")
var contagem = setInterval(() =>{
//life.classList.add('animar')
if (centesimos == 00) {
centesimos = 60
segundos--
life.style.width = (segundos / 15 * 100) + '%'
life.style.transition = 'linear 1.2s'
} else {
centesimos--
if (centesimos < 10) {
centesimos = '0'+centesimos
}
}
if (segundos == 0 && centesimos == 00) {
clearInterval(contagem)
}
contagemInicial.textContent = segundos+':'+centesimos
}, 14)
It's because optimization. Inactive pages have lower priority. You can work around this by calculating elapsed time between each update (recommended way) or use web workers since they not affected by this "issue". You can read more about this here, there are some great answers.

Chrome slows down javascript if page is not active [duplicate]

This question already has answers here:
How can I make setInterval also work when a tab is inactive in Chrome?
(16 answers)
Closed 5 years ago.
If I write a javascript code what uses setTimeout/setInterval, time will not be valid on Chrome if the related page isn't active.
To demonstrate, just simply create an html file with a js code like this:
<script>
var title = 1;
setInterval(function(){document.title = "X:"+title; title+=1}, 250);
</script>
Open page several time, and you'll see that if a page is not active, the title will increment only in abount 2 sec, instead of 250ms. It is a very critical issue in my development.
Does anyone know how to evade it? A simple Chrome options could be enought too if there is.
Just to mark it as not duplicate: It is not for animations, it is for background workings. The provided example is very accurate! I need to run script in very accurately and do operations fastly in backgrounded tabs. I know, 99,9999% of people does not need it...
Neither function is considered accurate by intention. You never should rely on provided timespans. This inaccuracy can be stressed to some amount by browser when your page isn't visible.
Actually it doesn't make sense to keep working in background using a regular webpage. If you really need to do that try some WebWorker instead. The webpage is for user interaction ... user interaction does not happen in background by intention. Processing things in background is best put in a worker thread. So, it's all about runtime context matching code's conceptual intention.
Adding to what cepharum has, it is impossible to guarantee that your code will be execute every 250ms exactly. Chrome is not a real time operating system, and neither is your code. Depending on the implementation of the interpreter, it may even experience drifts and delays.
With that being said, if you only want to reduce the delay, you can use a worker to trick the system by creating a new thread that will not have its refresh rate limited:
function createWorker(main){
var blob = new Blob(
["(" + main.toString() + ")(self)"],
{type: "text/javascript"}
);
return new Worker(window.URL.createObjectURL(blob));
}
// Worker
var worker = createWorker(function(self){
setInterval(function(){
self.postMessage(Date.now());
}, 250);
});
worker.onmessage = function(e) {
console.log("Worker: " + e.data);
}
https://jsfiddle.net/DerekL/ouzcdh9g/
I ran into the same issue before, the way I solved it was to use math to calculate the time difference, instead of rely on the setInterval being reliable. E.g.
var title = 1;
var tickTime = (new Date()).getTime();
setInterval(function(){
var now = (new Date()).getTime();
document.title = "X:"+title;
// you can adjust the math calculation below to
// meet your requirements
title+= (now - tickTime)/250;
tickTime = now;
}, 250);

something is not right with console.time();

I am testing my javascript's speed using the console.time(); method, so it logs the loading time of a function on load.
if (window.devicePixelRatio > 1) {
var images = $('img');
console.time('testing');
var imagesObj = images.length;
for ( var i = 0; i < imagesObj; i++ ) {
var lowres = images.eq(i).attr('src'),
highres = lowres.replace(".", "_2x.");
images.eq(i).attr('src', highres);
}
console.timeEnd('testing');
}
But every time I reload the page it gives me a pretty different value. Should it have this behaviour? Shouldn't it give me a consistent value?
I have loaded it 5 times in a row and the values are the following:
5.051 ms
4.977 ms
8.009 ms
5.325 ms
6.951 ms
I am running this on XAMPP and in Chrome btw.
Thanks in advance
console.time/endTime is working correctly and the timing does indeed fluctuate by a tiny amount.
However, when dealing with such small numbers - the timings are all less than 1/100 of a second! - the deviation is irrelevant and can be influenced by a huge number of factors.
There is always variation, could be caused by a number of things.
server responding slightly slower (hat can also block other parts of the browser)
your processor is doing something in the mean time
your processor clocked down to save power
random latency in the network
browser extension doing something in the background
Also, Firefox has a system that intelligently tries to optimize javascript execution, in most cases it will perform better but it is somewhat random.

Does JavaScript provide a high resolution timer?

Does JavaScript provide a high resolution timer?
I've written a few game engines from scratch, some in C, some in Java, and some in Flash. I always follow the same basic model when it comes to animations and interactive graphics. Create a basic class/structure with the following design:
void init() { /* Called once, preload essential resources here. */ }
void update(double time) { /* Updates game/animation state using high resolution time. */ }
void render(double time) { /* Updates screen graphics using high resolution time. */ }
void run()
{
double time;
init();
while (!done)
{
time = queryTime();
update(time);
render(time);
}
}
Time is so important to smooth animations and game state calculations. In native code Windows, I use QueryPerformanceCounter() and QueryPerformanceFrequency() to perform the role of queryTime() in each game loop and pass the time to update/render. In Java, I use System.nanoTime().
What's the equivalent in JavaScript? That is, some function like queryTime() which returns a time value with a high degree of accuracy (sub millisecond). From what I've heard the best accuracy you can get in JavaScript is about 15 ms ... which is horrible for animation.
Almost all modern browsers provide a high resolution timer. It's the "High Resolution Time" W3C standard: http://www.w3.org/TR/hr-time/#sec-DOMHighResTimeStamp.
It allows you to get a sub-millisecond accurate timestamp by calling window.performance.now(). This returns a time stamp in ms, but it is a float so you still get sub-millisecond resolution.
Very old browsers may implement a "prefixed" version of this standard, e.g. WebKit based browsers used to implement window.performance.webkitNow()
Here is some code you can use to get the the accurate timestamp when available and fallback to standard precision otherwise:
if (window.performance.now) {
console.log("Using high performance timer");
getTimestamp = function() { return window.performance.now(); };
} else {
if (window.performance.webkitNow) {
console.log("Using webkit high performance timer");
getTimestamp = function() { return window.performance.webkitNow(); };
} else {
console.log("Using low performance timer");
getTimestamp = function() { return new Date().getTime(); };
}
}
getTimestamp();
Note that this getTimestamp() function does not return a value that represents the current date/time. The returned value can only be used to measure time-periods, by subtracting two different timestamps.
E.g.
var t1 = getTimestamp();
//... some other code
var t2 = getTimestamp();
console.log("Time delta: " + (t2 - t1));
See #h3r3's answer—it is the correct answer.
Milliseconds are the best you can hope for in JavaScript. And, like you said, it isn't very accurate. See Stack Overflow question Microsecond timing in JavaScript.
timer.js purports to provide up to microsecond resolution, but it is only available for Google Chrome.
Update: timer.js does not support microsecond resolution. It just multiplies millisecond count by 1000.
Sorry, there isn't better news!
Instead of while (true)/setInterval, use recursive requestAnimationFrame. It will run smoother than timeout based animations. It provides timestamps if you need your animation to run at slower path.
As of now (February 25, 2013), the quality of high-performance times in Chrome 24 is pretty horrible.
var old = 0;
for (var i=0; i<10; i++) {
var t = window.performance.now();
var d = t - old;
old = t;
console.log(t + ' += ' +d);
}
outputs something like this:
609689.000000013 += 609689.000000013
609689.9999999441 += 0.9999999310821295
609689.9999999441 += 0
609689.9999999441 += 0
609689.9999999441 += 0
609690.9999999916 += 1.0000000474974513
609690.9999999916 += 0
609690.9999999916 += 0
609691.9999999227 += 0.9999999310821295
609691.9999999227 += 0
Which shows that
1) Sampling happens rarely
2) The precision is still around 1ms, not in the microsecond range.
Here's what your code should look like in JavaScript, so it doesn't block the user interface and doesn't use window.requestAnimationFrame which does not work cross-browser.
/* Called once, preload essential resources here. */
function init() {}
/* Updates game/animation state */
function update(time) {}
/* Updates screen graphics */
function render(time) {}
window.onload = function()
{
var time;
var done = false;
init();
// Using setTimeout passing zero makes the animate function run
// as soon as possible, but yielding first.
setTimeout(animate, 0);
function animate () {
time = new Date();
update(time);
render(time);
if (!done) {
setTimeout(animate, 0);
}
}
}
A problem with this approach is that the animate() may get called more often than the screen gets updated (at 60 Hz it won't update more often than abot every 16 ms), causing extra rendering that never makes it to the screen. That's why you should stick with requestAnimationFrame if possible.
Because this comes up when searching for JavaScript and high resolution timer, it is worth noting that window.performance.now is now functional (at least in Google Chrome v. 26) and provides ~microsecond resolution.
var d = 0;
var p = window.performance;
for(var i=0; i<10; i++) {
d = -1 * (p.now() - p.now());
console.log(d*1000);
}
It gave me this (in microseconds):
5.0000089686363935
3.9999722503125668
1.00000761449337
1.00000761449337
1.00000761449337
1.9999861251562834
1.9999861251562834
1.00000761449337
1.00000761449337
0.9999785106629133
I ran some stats on a few sets of 10k+ results. Minimum is about 1 microsecond, and the mean is about 1.25 microseconds on my machine (MacBook Air). Occasionally there are high outliers at the 100+ microsecond mark, but there were frequent results above 10 microseconds.
So the high-resolution timer is now capable of timing subtraction at microsecond resolution.
Node.js has a high resolution timer, too.
process.hrtime()
See the documentation for details
You can use CSS 3 transforms for simple animations that will get full hardware acceleration and will run silky smooth on most modern browsers... If you're expecting smooth animations on WebGL you're pretty much out of luck, because there's no submillisecond precision on JavaScript.
Currently, there's a lot of progress on enabling game related technologies for the web (see for example the mouse lock draft which is being actively developed our the fullscreen API... Maybe you can start the movement for microsecond precision timers in JavaScript ;-)
Just now I search for such solution, and found this thread. As I can see, all measurements done incorrect, because nobody know how work console.log function. From my experience (and practice) it take too much time, and even work asynchronously.
Just compare this code samples:
var old = 0;
for (var i=0; i<10; i++) {
var t = window.performance.now();
var d = t - old;
old = t;
console.log(t + ' += ' +d);
}
and this
var old = 0;
var out = [];
for (var i=0; i<10; i++) {
var t = window.performance.now();
var d = t - old;
old = t;
out.push(t + ' += ' +d)
}
console.log(out);
Besides the already provided excellent answers, you may also have a look at marky, a
high-resolution JavaScript timer based on performance.mark/measure
(461 bytes min+gz)
It also includes dev tools visualizations and is tested in a broad range of browsers.
Node supports nanoseconds via process.hrtime.bigint(), added in v10.7.0.
From the documentation:
The bigint version of the process.hrtime() method returning the current high-resolution real time in nanoseconds as a bigint.
Unlike process.hrtime(), it does not support an additional time argument since the difference can just be computed directly by subtraction of the two bigints.
import { hrtime } from 'process';
const start = hrtime.bigint();
// 191051479007711n
setTimeout(() => {
const end = hrtime.bigint();
// 191052633396993n
console.log(`Benchmark took ${end - start} nanoseconds`);
// Benchmark took 1154389282 nanoseconds
}, 1000);

How to tell what's causing slow HTML5 Canvas performance?

How can I tell if the canvas's slow performance is caused by the drawing itself, or the underlying logic that calculates what should be drawn and where?
The second part of my question is: how to calculate canvas fps? Here's how I did it, seems logical to me, but I can be absolutely wrong too. Is this the right way to do it?
var fps = 0;
setInterval(draw, 1000/30);
setInterval(checkFps, 1000);
function draw() {
//...
fps++;
}
function checkFps() {
$("#fps").html(fps);
fps = 0;
}
Edit:
I replaced the above with the following, according to Nathan's comments:
var lastTimeStamp = new Date().getTime();
function draw() {
//...
var now = new Date().getTime();
$("#fps").html(Math.floor(1000/(now - lastTimeStamp)));
lastTimeStamp = now;
}
So how's this one? You could also calculate only the difference in ms since the last update, performance differences can be seen that way too. By the way, I also did a side-by-side comparison of the two, and they usually moved pretty much together (a difference of 2 at most), however, the latter one had bigger spikes, when performance was extraordinarily low.
Your FPS code is definitely wrong
setInterval(checkFps, 1000);
No-one assures this function will be called exactly every second (it could be more than 1000ms, or less - but probably more), so
function checkFps() {
$("#fps").html(fps);
fps = 0;
}
is wrong (if fps is 32 at that moment it is possible that you have 32 frames in 1.5s (extreme case))
beter is to see what was the real time passes since the last update and calculate the realtimepassed / frames (I'm sure javascript has function to get the time, but I'm not sure if it will be accurate enough = ms or better)
fps is btw not a good name, it contains the number of frames (since last update), not the number of frames per second, so frames would be a better name.
In the same way
setInterval(draw, 1000/30);
is wrong, since you want to achieve a FPS of 30, but since the setInterval is not very accurate (and is probably going to wait longer than you say, you will end up with lower FPS even if the CPU is able to handle the load)
Webkit and Firebug both provide profiling tools to see where CPU cycles are being spent in your javascript code. I'd recommend starting there.
For the FPS calculation, I don't think your code is going to work, but I don't have any good recommendation :(
Reason being: Most (all?) browsers use a dedicated thread for running javascript and a different thread for running UI updates. If the Javascript thread is busy, the UI thread won't be triggered.
So, you can run some javascript looping code that'll "update" the UI 1000 times in succession (for instance, setting the color of some text) - but unless you add a setTimeout to allow the UI thread to paint the change, you won't see any changes until the 1000 iterations are finished.
That said, I don't know if you can assertively increment your fps counter at the end of the draw() routine. Sure, your javascript function has finished, but did the browser actually draw?
Check if you dont use some innerHTML method to debug your project. This can slow your project in a way you can't imagine, especially if you do some concatenation like this innerHTML += newDebugValues;
Or like desau said, profile your cpu usage with firebug or webkit inner debugger.

Categories

Resources