Node.JS Architecture

Basically, Node.js is a combination of Google’s V8 JavaScript engine, an event loop, and a low-level I/O API.

Below diagram denotes a simplified version of Node.js architecture.

Following are the 3 main parts

  • V8 Engine
  • js Bindings (Node API)
  • An event loop

JavaScript Engine

A JavaScript engine is a program or an interpreter which executes JavaScript code.

Below mentioned are some of the various JavaScript engines :-

  • Rhino from Mozilla
  • JavaScriptCode developed by Apple for Safari
  • JerryScript a lightweight engine for Internet of things
  • Chakra (JScript9) for Internet Explorer
  • Chakra (JavaScript) for Microsoft Edge
  • V8 from Google and so on.

Since Node.js uses Google V8, coverage of other JavaScript engines are beyond the scope of this article.

Google V8

V8 is Google’s open source JavaScript engine, written in C++. It is not only used in Google Chrome but is also the part of popular Node.js. V8 directly translates JavaScript code into efficient machine code using JIT (Just-In-Time) compiler instead of using an interpreter.

Inside, the V8 engine, consists of several threads.

  • A thread for fetching JS code, compiling it & then executing it.
  • A separate thread for compiling, so that the main thread can keep executing while the former is optimizing the code .
  • A Profiler thread which tells the runtime on which methods we spend more time so that Crankshaft can try to optimize them.
  • Garbage Collection threads

Full-Codegen – At start , V8 utilizes Full-Codegen compiler which directly transforms parsed JavaScript code into machine code without any intermediate bytecode, this is why V8 does not needs an interpreter.This allows to start execution of the code as soon as possible.

Crankshaft – Now another thread starts using another compiler “Crankshaft” . Its main role is optimization.

In-lining – Inlining replaces the line of code where the function is called with the body of the called function for faster execution. C++ developers are used to with this concept.

Hidden Classes – It’s difficult for compiler to optimize dynamically typed language such as JavaScript because types of objects can be changed at runtime. At runtime V8 creates hidden classes that are attached objects to track their layout. So it is very important to maintain the shape of your objects so that V8 is able to optimize code efficiently.

Inline Caching – Inline caching relies on the observation that repeated calls to the same method tend to occur on the same type of object.  V8 uses a cache for the type of objects that were passed as a parameter in recent method calls and uses this knowledge to make an assumption about the type of object that will be passed as a parameter in the future. If this assumption is right, it can skip the process of figuring out how to access the object’s properties and can use the stored information from cache .

Garbage collection – Garbage collection is freeing up memory which is not in use anymore. Languages such as C have APIs for this like free() but JavaScript lacks such API. So this memory management task is handled by V8.

Event Loop

Node.js is an event-based platform. This means that everything that happens in Node is the reaction to an event. A transaction passing through Node traverses a cascade of callbacks. Abstracted away from the developer, this is all handled by a library called libuv which provides a mechanism called an event loop.

There is only one thread that executes JavaScript code and this is the thread where the event loop is running. The execution of callbacks (know that every userland code in a running Node.js application is a callback) is done by the event loop.

Libuv by default creates a thread pool with four threads to offload asynchronous work to. Today’s operating systems already provide asynchronous interfaces for many I/O tasks (e.g. AIO on Linux). Whenever possible, libuv will use those asynchronous interfaces, avoiding usage of the thread pool. The same applies to third party subsystems like databases. Here the authors of the driver will rather use the asynchronous interface than utilizing a thread pool. In short: Only if there is no other way, the thread pool will be used for asynchronous I/O.

While there are queue-like structures involved, the event loop does not run through and process a stack. The event loop as a process is a set of phases with specific tasks that are processed in a round-robin manner.

 

Share this post
[social_warfare]
Node Internal Working
Node.js Installation

Get industry recognized certification – Contact us

keyboard_arrow_up