22

I know there's a minimum of 1 millisecond in the setInterval method in javascript. Can I speed this up even more? Like using microseconds?

for what i need this:

i make a canvas css/js animation. it's a simple line, which bends into a cure and back to a line. i have a slider to adjust the speed of this animation. so the lowest slider value would be really fast and the highest really slow. is that understandable? thanks!

trnc
  • 20,581
  • 21
  • 60
  • 98
  • 3
    why not just remove setInterval and have it instant – KJYe.Name Mar 14 '11 at 13:12
  • 1
    As the execution of the callbacks is not guaranteed to take place after the exact time has passed, I believe that you just cannot be more precise. – Felix Kling Mar 14 '11 at 13:15
  • Could you please post more context on what you are trying to do, accompanied with some code examples? I am interested in your use case. Thanks. – Mahesh Velaga Mar 14 '11 at 13:15
  • See also [How to create an accurate timer in javascript?](https://stackoverflow.com/q/29971898/1048572) – Bergi Jun 07 '17 at 12:23

6 Answers6

29

Update:

Please note that when this answer was written, the question was:

I know there's a minimum of 1 millisecond in the setInterval method in javascript. Can I speed this up even more? Like using microseconds?

Later it was edited to include the information about canvas animation and with that new information the correct answer would be using the window.requestAnimationFrame method:

function step(timestamp) {
  // do something for every frame
  window.requestAnimationFrame(step);
}
window.requestAnimationFrame(step);

The step callback gets a DOMHighResTimeStamp timestamp with a precision of 1 microsecond as an argument every time it gets invoked, which is once every time the screen gets refreshed (there's no need to draw anything more frequently because it wouldn't get displayed anyway).

Originally the question was specifically about speeding up the setInterval method, and my original answer was about doing anything in general more frequently than the minimum delay of setInterval allows (which is 4ms for the nesting levels greater than 5 according to the the WHATWG specification, section 8.4 Timers, or 4ms for the nesting levels of 4 or higher according to this post by James Robinson, and historically it used to work differently).

Original answer:

I don't really know what are you trying to do so I can only speak from experience of what people usually want to do with it.

If you want to call setInterval using microseconds, then the code you want to run has to take considerably less then a millisecond, or otherwise it wouldn't make sense in a single-threaded event loop.

You don't have to worry about blocking the browser for a few milcroseconds so I would suggest using something like this – instead of having:

setInterval(function () {
    // YOUR CODE
}, 1/100);

Try doing:

setInterval(function () {
    for (var i = 0; i < 1000; i++) {
        // YOUR CODE
    }
}, 10);

You will actually make your code more efficient by avoiding the callback calling overhead and having longer intervals will make your code run more predictably.

Also no one is going to notice that your code runs in bursts 1000 times every 1/100 of a second, because there's a chance that the browser itself already runs in such bursts thanks to the OS-level process scheduling, and also the screen won't get refreshed faster anyway.

An experiment

Ok, now some experiment. Try this code to see what is actually the shortest interval for your browser:

var start = new Date();
var i = 0, interval = setInterval(function(){
    if (++i >= 1000) {
        var end = new Date();
        alert("The average interval was "
              + ((end-start)/1000)) + " milliseconds";
        clearInterval(interval);
    }
}, 0);

Note that it won't even be consistent on the same browser. It depends on your system load for example.

Test your browser

Try THIS FIDDLE to test your browser and post your result in the comments if you like. I wonder what will be the record.

rsp
  • 107,747
  • 29
  • 201
  • 177
  • can a function be called in the for loop? – Ashwin May 29 '12 at 08:35
  • `The average interval was 4.003 milliseconds Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36` – Vitim.us Jun 05 '17 at 02:48
  • `The average interval was 4.057 milliseconds Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36` – Anonymous May 16 '18 at 15:54
5

Note that some browsers won't accept intervals smaller even than 50 milliseconds. If You pass a smaller interval, they will use the smallest they are able to use.

Piotr Salaciak
  • 1,653
  • 1
  • 15
  • 28
5

The minimum time is different depending on the browser. A good explanation is here: http://www.adequatelygood.com/2010/2/Minimum-Timer-Intervals-in-JavaScript

idbentley
  • 4,188
  • 3
  • 34
  • 50
2

FYI, it's gonna be useless to do it less than a few milliseconds between each interval, because canvas ops take a few milliseconds to do their own thing, while blocking your main loop at the same time (single threaded). Doing 1/100 for milliseconds actually gets rounded up to 16 in classical browsers, and 5 milliseconds in chrome.

You're doing it wrong if you're trying to time your animation in javascript to microseconds, because that's a futile goal. garbage collection, busy loop timing variance will hurt you, not to mention if you draw too fast you might get frame tearing.

SOLUTION: use requestAnimationFrame to get the maximum FPS out of a browser, and don't forget to provide a fallback to setInterval(..., 16).

https://developer.mozilla.org/en/DOM/window.mozRequestAnimationFrame http://dev.chromium.org/developers/design-documents/requestanimationframe-implementation

Grant Galitz
  • 216
  • 3
  • 5
0

I know this is an old question, but it still has no accepted answer.

You don't need to have a shorter interval to increase the rate at which your line appears to bend. You keep the interval the same, this is your framerate, and you simply change the stepping between states of the line. It bends more between frames if it is bending quickly.

Here is an example from something I have been playing around with.

var radius = 0;
var hor = 0;
var frameTime = 1000/60;
var step = 1;

setInterval(function () {
    var draw = document.getElementById('draw');
    var context = draw.getContext('2d');

    draw.width = draw.width;

    context.fillStyle = '#ffffff';
    context.beginPath();
    context.arc(draw.width/2,draw.height/2,radius,0,Math.PI*2,true);
    context.closePath();
    context.stroke();
    context.fill();

    radius = (radius+(step*frameTime))%(draw.height/2);
}, frameTime);

It's a very simple animation, just a circle which grows to the size of the canvas and then starts back from nothing. Here, the variable 'step' controls the rate of the animation. 'frameTime' is the time between frames.

I hope I have properly understood what the problem is. I know you probably got over it a long time ago, but I thought it best to have an answer here for anybody with a similar problem in future.

Luke
  • 2,434
  • 9
  • 39
  • 64
-3

I'm not sure if it would work, but try diving a millisecond to break it down further. e.g.

setTimeout("moretext()",1 / 100);

Ian
  • 879
  • 8
  • 21