Random Notes about Node JS
2 min readHow timers work in node under the hood?
Whenever you set a timer in Node, it essentially calculates the exact time when the timer should expire based on the current time. It then registers the expiration time with the kernel. Node continuously polls the kernel using epoll_pwait(Refer this for more info. The kernel maintains these timers using a min-heap data structure to always return the lowest possible expiration time.setTimeout(() = { // do something ... }, 3000) setTimeout(() = { // do something ... }, 2000) setTimeout(() = { // do something ... }, 5000)From the above example, we have three setTimeout calls. When this code runs, Node registers each timeout in the kernel with the current timestamp + timeout. For instance, if the code runs at 12:00:00 AM IST, the kernel will have the following timer entries:
12:00:03 AM(3000ms)
12:00:02 AM(2000ms)
12:00:05 AM(5000ms)Node will then continuously poll the kernel(using the event loop and epoll_pwait). The kernel, maintaining the timers in a min-heap, will always return the lowest/nearest expiration time. Node then compares the returned time with the current time and executes the appropriate callback.
Phases in Node
Initial phase: This is the phase where our synchronous code executes line by line. before this phase all our required modules/files will be executed.
Timer phase: This is where our timers will be setup and starts running.
pending callback phase: Basically some error callbacks will be executed in this.
idle/prepare phase: This is where node does epoll_ctl phases, initializes the epoll queue etc.
poll phase: This is the important phase, this is where our network io, file io etc everything will be polled and be executed.
check phase: This will be executed after the poll phase, so we can able to use setImmediate here to do something after our poll phase.
close phase: This will be executed for any close connection related callbacks, like socket.close, req.end etc.
setTimeout(() => console.log("timer phase"), 0) // 4 process.nextTick(() => console.log("next tick phase")) // 3 fetch("https://google.com").then(d => { console.log("Poll phase") // may or may not execute before/after 5 based on network latency setImmediate(() => { console.log("Set immediate phase or check phase") // 8 }) process.nextTick(() => console.log("Next tick inside poll")) // 7 setTimeout(() => console.log("timer phase inside pol "), 0) // 9 }) setImmediate(() => { console.log("Set immediate phase or check phase") // 5 }) console.log("Program starts") // 1 for (let i = 0; i < 100_000_000; i++){}; console.log("Program ends") // 2
Above is a simple code example on how node phases work
