V8, Libuv
- Node.js uses the V8 engine to run javascript and the Libuv library to communicate with the OS.
- Libuv also implements the Event Loop, which is responsible for the ‘non- blocking I/O’ and ‘event driven’ mechanism.
Event loop
- The event loop is a sequence of phases that are processed one after another.
- Each phase has its own callbacks queue (for example, the Timers phase queue will have setTimeout and setInterval callbacks).
- After executing all the callbacks in a phase, the loop will continue to the next phase.
- When the queues in all phases are empty, the event loop will exit and we are done.
Event loop execution example
Phases overview
- timers: this phase executes callbacks scheduled by setTimeout() and setInterval().
- pending callbacks: executes I/O callbacks deferred to the next loop iteration, responsible for handling errors returned from OS related actions.
- idle, prepare: only used internally.
- poll: retrieve new I/O events, execute I/O related callbacks (almost all with the exception of close callbacks, the ones scheduled by timers, and setImmediate()); node will block here when appropriate.
- check: setImmediate() callbacks are invoked here.
- close callbacks: some close callbacks, e.g. socket.on(‘close’, …).
- Between each run of the event loop, Node.js checks if it is waiting for any asynchronous I/O or timers and shuts down cleanly if there are not any.
Event loop code level
src/node.cc
1 2 3
inline int Start ( Isolate* isolate, IsolateData* isolate_data, int argc, const char* const* argv, int exec_argc, const char* const* exec_argv )
src/node.cc
1
uv_run(env.event_loop(), UV_RUN_DEFAULT);
deps/uv/src/unix/core.c
link1 2 3 4 5 6 7 8 9 10 11 12 13 14
while (r != 0 && loop -> stop_flag == 0) { uv__update_time(loop); // update loop time uv__run_timers(loop); // timers ran_pending = uv__run_pending(loop); // handling IO callbacks uv__run_idle(loop); uv__run_prepare(loop); timeout = 0; if ((mode == UV_RUN_ONCE && !ran_pending) || mode == UV_RUN_DEFAULT) timeout = uv_backend_timeout(loop); uv__io_poll(loop, timeout); // handling IO poll eventqueue uv__run_check(loop); // handling check eventqueue uv__run_closing_handles(loop); // handling close eventqueue r = uv__loop_alive(loop); // check event loop state if (mode == UV_RUN_ONCE || mode == UV_RUN_NOWAIT) break; }