One of my friend commented on my previous post and suggested that I should explain a bit about the Timers, so here it is.
What is Time? Umm.. A measurement from a reference point in history? Or that counted using Radium? Whatever, it doesn’t really matter, unless we start to have bad times in life, does it? Well its kind of cool question that you can look around the web and figure out the exact answer about this fourth dimension.
First, I remember saying there was one homework that I suggested in my previous post, got your hands on it? Oh well, no worries! ☺
What? You haven’t read the previous post? Here you go.
What are Timers?
Try changing the length of the Array in the second case and you will see the change in the Timeout fire time.
We will be taking NSPR for the purpose. So, lets see what a Timeout is:
Browsers works on an event queue model, where all the events gets queued and then browser picks up one entry from the queue at a time and execute it, to visualise, it looks like this:
So what are timers? They are threads, that are timed after which they push callback in the event queue and waits for its chance to get executed, so if you are doing some blocking task, allocating big memory chunk, looping over a big set of data, the chances of your callback getting delayed increases.
The thread library that Netscape uses is a customised form of pthread, they have a wrapper above it which they named BThread(Binary Thread, I guess), it handles all of the TLS(Thread Local Storage) and Code contexts that needs to be triggered.
To provide the thread usability, the underlying engine of Firefox i.e. Gecko uses XPCOM and interface it with the core JS Engine(what are these? will cover them later in a separate blog).
If we talk about JS, then we have only 2 options to have Timers i.e. setInterval or setTimeout
Law: Interval = Timeout (somewhat)
setTimeout, setInterval returns you the Unique Id of the Timer, and the cool thing, two consecutive setTimeout/setInterval will never have a sequential ID’s(Why? that’s today’s homework☺). These ID’s are integer values that means you can add, subtract, divide, multiply there values, but be careful don’t loose those values.
Actually, setInterval simply means to trigger your callback after a certain amount of time, right? And timeout means to execute a callback after a certain time with little difference, Interval is repeating and Timeout isn’t, but functionally both are same thing. So why can’t Timeout be made subset of Interval? That is called smart work ☺ rather then writing a complete new implementation, browsers utilise Timeout to simulate the Interval Timers.
Law: clearInterval = clearTimeout
Well, you might not agree with my law stated above, right? Let me prove it for you :D
Hahaha :D Yeah, they both are same thing, just as setInterval and setTimeout. They take the Unique ID’s that setTimeout/Interval returns to you. Simple Job, they just kills the thread, GC everything, clean memory.
Well your Timers will rarely be fired in time, because there will be dozen of things that you will be manipulating on DOM, right? Like your event listeners, they too push on queue there callbacks, similarly are your Ajax callbacks, HTML5 API’s callbacks. They all run in that single Event Loop, so probability of timers been fired in time is very low. In the end only one callback is been executed by the DOM, and if you add something like a very big for loop, everything will hang up, because the event loop will never reach the end of current callback and could never pick up the next queue item, and your complete window will freeze!(Try it!)
Animations & Frames
Previously when requestAnimationFrame function wasn’t available to the developers, we use to create our animations using setInterval(), well today also you can create animations using setInterval but they seems to be bit laggy if you compare them with that what you can achieve with CSS3 animations.
Okay, so let’s study about what are Animations Frames.
CSS Animations and requestAnimationFrame works in a different domain and are different from Timers library which setTimeout and setInterval uses, Oh not the beneath library i.e. bthreads/pthreads but the interface which they use. The requestAnimationFrame’s main motive is to achieve 60fps(Frames per second) rate of Animation, unlike JS Timers which can be delayed because they are working into a single event model natively.
Animation Frames are moved outside it to achieve this because of limitations that we face in ordinary Timers. But still the animation frame code execution depends on the manipulation you will be doing in the callback of requestAnimationFrame.
The Animation Frames are allocated a separate Queue Model and handler, in order to speed up the Animation CallBacks, it utilises a perfect approach of nextTick() which nodeJS uses with a difference, nodeJS looks it under process.nextTick(), which is like looking for a time frame when in the next turn process will be idle whereas the Animation Frames Ticker is ticked after ever 1ms, it looks into the queue, fire all the handlers, sleeps for 1ms and then again, pick up all the animation callbacks in the queue and fire them.
Now, let say you pushed a callback at Time T in the event Queue, at
T = t
Browser will pick up that callback from the queue and will fire it after 1ms,
T = T+1ms
Now this callback execution time defines the next time cycle, so let say your callback took 3ms to complete its execution.
Next Queue Time(T) = T+1+3
Although in between those 3ms, browser has checked the event queue thrice, but your callback wasn’t queued back until then, in the next 1ms cycle, browser will again check the event queue and this time it will find your callback there, it will fire it, and the cycle repeats.
Eventually, you will have a delay of 3ms at each cycle, In a fraction of second Browser checks the event queue at 60Hz(60fps) rate, i.e. after every 1ms. As your timers have delayed for 3ms at each cycle, eventually in 1 second, it will be fired only ~30 times which is a 30Hz(fps) rate of animation, it will be laggy, a lot!
In the above code the callback function step is what will determine the next callback time valuation, however, the DOM’s goal to fire the event listener is to fire your callback in time and not to wait but you know Threads sharing same memory space and memory can have an awkward behaviour, so browser waits until your callback get fired before firing your callback. So while writing tedious animation and to achieve 60fps, just make sure your callback completes its task in 1–2ms. To optimise things, browsers suspend Animation Frames if they don’t have focus to save memory and utilise more GPU/CPU for other tabs.
Well if you really need an exact ~1ms timer to perform some task/animation, requestAnimationFrame is your bet!
Still laggy? Need even better animation? Use CSS3 animations! There callbacks don’t compute, they just get fired! The only drawback is control, you can’t control behaviour of your animation frames that’s why browsers exposed requestAnimationFrame interface.
Timers are pretty fun thing but everyone knows, no one can ever have real time timers(atleast on nano scale and sometimes on micro, it depends), real time systems rarely exists, so we should use the time frame provided to us very efficiently, well I might sound like a philosopher but this same thing applies to our life too! ☺
Quest: What makes your CPU burn too much calories when you run a high graphic animation in your browser or system?
Well, its the number of threads actually, which are responsible for it who are all painting the screen/refreshing the screen simultaneously. In a game, there are several threads that are working at a time, Shaders, Texture Loaders, Movement Controller, Bot Controller, they all are individual threads(or multiple of them, depends upon the architecture which developer choose) which are performing a load of computational tasks on CPU, and there are almost more then 10000 contextual switches it has to perform to keep everything running and in sync in 1ms.
Oh yeah, here is our little child browser, pitty on him, but thats the only model he found best(so as NodeJS).
That’s it for this week, let me know, what you feel about the blog, things I should improve/focus more on. Leave your comments and let me know what should I write next.
❤ Love! ☺