Posts NODE.JS Archiecture (2)
Post
Cancel

NODE.JS Archiecture (2)

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

image

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 link
    1
    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; 
    }
    

References

This post is licensed under CC BY 4.0 by the author.