Understanding and Debugging in NodeJS

March 06, 2018 0 Comments

Understanding and Debugging in NodeJS

 

 

This article will give you deep understanding of NodeJS, how to develop applications in NodeJS and how to debug NodeJS applications.

Introduction to NodeJS

NodeJS is asynchronous event driven JavaScript runtime environment. It is cross platform (Windows, Linex, Unix, Mac OS X etc), light weight, efficient and freely available to everyone. NodeJS is used for executing JavaScript code to the server side to produce dynamic web page content. It is built on Chrome’s V8 JavaScript Engine. NodeJS is used to create dynamic web pages, it can add, remove and update data in your database. With NodeJS you can use your JavaScript skills outside of the browser that is to build dynamic http servers. NodeJS has many exciting features like asynchronous API’s, very fast engine, uses single threaded model and no buffering. NodeJS works best for I/O bound and JSON APIs based applications. It is not suitable for CPU based intensive applications.

You can download NodeJS from https://nodejs.org/en/ . Run NodeJS setup and click next. NodeJS will install in your system.

Let’s start coding in NodeJS. Open NodeJS and create a JavaScript file. NodeJS application has three components necessary. Here let’s examine

Importing required modules: Require directive is used to load the NodeJS module.

var http = require(“http”);

This http variable will store the returned HTTP instance.

Creating Server: HTTP.createServer() method is used to create a server instance

http.createServer(function (request, response){
response.writeHead(200, {‘Content-type’ : ‘text/plain’});
response.end(‘Hello World\n’);
}).listen(8081);
Console.log(‘Server running at http://127.0.0.1:8081’;);
}

This will send an http header with status 200 and content type as plain text. It will send the response as Hello World to the server running at 127.0.0.1:8081.

Request/Response: Response will be send to your local machine address. Here is complete Hello world example in NodeJS.

var http = require("http");
http.createServer(function (request, response) {
// Send the HTTP header
// HTTP Status: 200 : OK
// Content Type: text/plain
response.writeHead(200, {'Content-Type': 'text/plain'});

// Send the response body as "Hello World"
response.end('Hello World\n');
}).listen(8081);
// Console will print the message
console.log('Server running at http://127.0.0.1:8081/');

Save your hello world file with JavaScript extension. Now run NodeJS command line and type

Node helloWorld.js, it will show server running message on the terminal.

Now open your browser and check the response at http://127.0.01:8081

Here is how it responded

Socket.IO Example

To handle long term connections socket.IO is used. Create another JavaScript file name as socket.js. Open it and paste the following code.

//varibale instance to hold http responce 
var HTTPvar = require('http'),
io = require('/path/to/socket.io');
//port number for server
var PortNumber = 8081;
//creating http server by using create server method
var HTTPserver = HTTPvar.createServer();
//starting the server by  passing port number as a parameter to the listen method
HTTPserver.listen(PortNumber);
//Attaching Socket.IO to the HTTP Server
var socket = io.listen(HTTPserver);
console.log('Server running on port : ' + PortNumber);

Open NodeJS terminal and run socket.js to see the output. Open your browser for the response.

Now you have learned how to code in NodeJS and how to execute it on the server side.

NodeJS architecture is very interesting. Single threaded, non-blocking I/O and event loops make it fast and efficient. Let’s explore them one by one.

  • Single threaded: Multi-threaded architecture creates separate threads for every single request which consumes CPU resources. In contrast to the multi-threaded, single threaded architecture has many plus points with it. To handle multiple concurrent clients all requests are run on the same thread. Single threaded mechanism saves CPU time by avoiding context switching. This makes it asynchronous. Asynchronous operations have better performance when they are single threaded as compared to the multi threaded architecture. Cluster module of NodeJS allows you to spawn several processes which are automatically connected via IPC channels.
  • Non blocking I/O: Non blocking I/O mechanism means it doesn’t waste CPU time in waiting next input or output. CallBack is used when any function is performing input/output request.
  • Event loops: Non blocking I/O calls emit an event after completion.

It has built in support for protocols like TCP, DNS and HTTP. These three technologies are used for real time web applications. Following diagram shows the layers in which NodeJS is built.

Here are different modules of NodeJS architecture

  • V8– V8 is Google’s open source JavaScript engine that resides in Chrome browser. Instead of interpreting JavaScript code on the fly like typical web browsers do, V8 translates your JS code into machine code so that it’s blazing fast. V8 is written in C++.
  • libuv– libuv is written in C language and originally developed to provide asynchronous I/O that includes asynchronous TCP & UDP sockets, (famous) event loop, asynchronous DNS resolution, file system read/write, and etc.
  • Application– here is your code, modules, and Node.js’ built in modules, written in JavaScript (or compiled to JS through TypeScript, CoffeeScript, etc.)
  • Binding– a binding basically is a wrapper around a library written in one language and expose the library to codes written in another language so that codes written in different languages can communicate.

Lets discuss memory leakage in nodeJS.

Memory leakage is incorrect memory allocation that is no longer needed and is not released.

The question is how to avoid memory leakage? If the goal is never to have memory leaks that’s hard what’s more important is understanding why memory leaks happen. Importantly being able to debug having the tools that you have experience with, which will let you debug those memory leaks.

Understanding memory leak

So let’s go through some examples.

app.get(‘/’, req res) => {
const garbage = new Array(1000);
res.status(200).send(‘hello world’);
)};

This is like a very simple express request handler the hello world app. The code is allocating a really big array inside this handler, is it garbage? Because I never do anything with it. But this is not a memory leak because Garbage Collector can see that you’re not using this anywhere. You’re not holding on to this object that you’ve allocated right there’s nothing that would prevent it from being garbage collected.

Let’s change this code little bit

app.get(‘/’, req res) => {
req.garbage = new Array(1000);
res.status(200).send(‘hello world’);
)};

I put the garbage in the request object so this is memory leak. When your request is done it comes in to express and sends a response back. Then it throws away all references to the request object so the request object is garbage.

So the necessary conditions is memory leaks happen when expected short lived objects are attached to long lived ones. Suppose this is an object I have allocated and I think it’s short-lived and then you go store it in draw into an object that’s really long-lived then that might be a memory leak.

Here is another example this is a bit contrived but I wanted to actually show you memory leak.

app.get(‘/’, (req, res)  => {
request.set( req.id, req);
res.status(200).send(‘hello world’);
)};

This is a memory leak because I have a module global map so there’s an object on the outside request and every time a single request comes into the server. I throw more stuff into that object the outermost object is going to live forever. So now you’re actually leaking all the requests that come in so this will quickly run out of memory.

Let’s examine another simple example

for ( let i=1; I <= 1e9; i++){
const{rss, heapTotal , external}
= process.memoryUsage();
console.log( i, rss, heapTotal, external);
}

The only thing this program is doing is looking at how much memory it’s consuming. This program will increase its memory footprint as you run it. It will run out of memory eventually so this is not quite obvious.

Now you have understood NodeJS architecture and coding in NodeJS, let’s start focusing on debugging. Debugging is the process of finding and removing bugs in any program or software. It is the integral part of software testing. While developing NodeJS applications, there are some serious chances of errors. To make sure your program/ application is error free, lets learn debugging.

There are many ways to debug your application, I will discuss few of them.

MemoryUsage():

If you are not using any tool, memory usage is the most basic thing that you can have. This has zero dependency. You don’t need anything, you can just put in your application.

const numeral = require(‘numeral’);
setInterval(() => {
const { rss, heapTotal} = process.memoryUsage();
console.log(‘rss’, numeral(rss).format(‘0.0 ib’),
‘heapTotal’, numeral(heapTotal).format(‘0.0 ib’));
},5000 );

There are some modules as follows:

Rss: It tells you how much resident set size of your application is. Means how much RAM your application is consuming this includes anything that v8,Node core and any other library is using. if your RSS is going up you probably have a memory leak.

External: this is any memory the node core is allocating for objects that it needs to connect between JavaScript and native site. So if you have a buffer this would go into the external memory.

HeapTotal: Heap total is the total amount of memory that is available for JavaScript objects. So if you have a memory leak in JavaScript you would probably see this number going up.

HeapUsed: Heap used is total space occupied by JavaScript object presently. It’s a bit more variable because it goes up and down as garbage collector works. You can look at that as well but heap total is probably a good enough metric to look at.

So if your overall external memory is going up that means maybe you’re leaking a buffer or some of the wrapper object that note core is using.

Console.log:

One of the most common form of debugging is the use of console.log statement. If you are not good at debugging you can use this console.log statement in your application to find low potential errors. It just simply prints on the screen. Nothing is like setting breakpoints or typical debugger stuff. It will console the message on your browser if you write it in the client’s side code. For the server side it will console the message on the editor.

Debugging with Node inspector:

Node inspector is a powerful JavaScript debugger for NodeJS applciations that uses the blink developer tools. It has many advanced features.

  • Navigate in your source files
  • Set breakpoints (and specify trigger conditions)
  • Step over, step in, step out, resume (continue)
  • Inspect scopes, variables, object properties
  • Hover your mouse over an expression in your source to display its value in a tooltip
  • Edit variables and object properties
  • Continue to location
  • Break on exceptions
  • Disable/enable all breakpoints
  • CPU and HEAP profiling
  • Network client requests inspection
  • Console output inspection

To install node inspector type $ npm install –g node-inspector. To start debugging type the following command

$ node-debug app.js

NodeJS tools for Visual Studio:

Visual Studio allows you to code JavaScript and TypeScript languages. Visual Studio code Node.js debugger communicates to the Node.js runtimes through wire protocols, the set of supported runtimes is determined by all runtimes supporting the wire protocols.

Procedure:

To set a breakpoint in app.js, put the editor cursor on the first line and press F9 or click in the editor left gutter next to the line numbers. A red circle will appear in the gutter.

To start debugging, select the Debug View in the Activity Bar.

You can now click Debug tool bar green arrow or press F5 to launch and debug “Hello World”. Your breakpoint will be hit and you can view and step through the simple application. Notice that VS Code displays an orange Status Bar to indicate it is in Debug mode and the DEBUG CONSOLE is displayed.

Conclusion:

In this tutorial you have deeply understood what NodeJS is, how to code in NodeJS , what are memory leaks and how to debug that memory leaks in your NodeJS applications. One of the good practice to avoid memory leaks is don’t copy others code, always try to write your own piece of code. This will save your time and efforts for finding memory leaks in your code.

original publish on Krissanawat.com


Tag cloud