Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Used memory never released in node js. Very strange

I've just finished to develop my first node.js app and now i'm testing it on my VPS. observing the use of resources of the process "node", I have noticed an increase in memory usage when a page (especially some) is requested. In particular, if the requested page is a static page, the increase is minimal. If the requested page is /admin the increase can be 1mb! Of course, when /admin is requested, my server does more things than serve a static page. He connects to mongodb, he performs 4 "find", he binds the results to an html template using bind. Now, what's the problem? This memory used, will be never released!!! So I thought there was a logical error in my code but then I did another test much more interesting.

Consider this very simple nodejs server:

 var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
}).listen(3000, 'my_public_ip');

if I try to make multiple requests with browser (simply by holding f5 for one minute), memory usage grows slowly and the memory used by the process will never be released, even after a long time and after closing the browser. Now, it's probable that in my /admin code there is some error (1mb of memory used and never released for each requests it's very high!), but i think that it's very strange that memory used by the simple script above will be never released! What do you think about this? There is a way to avoid it?

Also , (in my real server) , I used memwatch in thys way:

    var memwatch = require('memwatch');
    memwatch.on('leak', function(info) {
       console.log(info); 
       process.exit(1);
    });

If I perform multiple requests with browser , after about 10 seconds that i'm doing it, the process will exit and this is the error:

{ start: Wed Nov 26 2014 08:21:07 GMT-0500 (EST),
  end: Wed Nov 26 2014 08:22:04 GMT-0500 (EST),
  growth: 4775624,
  reason: 'heap growth over 5 consecutive GCs (57s) - 287.65 mb/hr' }

What does it mean?? It seems be related with garbage collector! I know that it would be better to paste my /admin code here but the snippet is very long and is related to global variables, so is impossible to understand without a copy of 200 lines :D. If you need more info i will give you!

like image 942
Radar155 Avatar asked Nov 26 '14 14:11

Radar155


People also ask

How do I check Nodejs memory usage?

memoryUsage() method is an inbuilt method of the process module that provides information about the current processes or runtime of a Node. js program. The memory usage method returns an object describing the memory usage in bytes of the Node.

How do I give Node js more memory?

If you want to increase the max memory for Node you can use --max_old_space_size option. You should set this with NODE_OPTIONS environment variable.

What is Node js default memory limit?

Tuning the Garbage Collector In Node < 12 , it sets a limit of 1.5 GB for long-lived objects by default. If this exceeds the memory available to your dyno, Node could allow your application to start paging memory to disk.


1 Answers

It's not surprising node is not releasing memory, most programs don't. They're greedy: if they run short, they get more memory from the system. If they have extra, they keep it to have for later.

The short sample server is not leaking memory. I ran a 14-minute test with node v0.10.29; memory use grows slowly only initially, then it stops. The rate of growth is less than one bit per http call, so it can't be leaking memory in the calls themselves. It may be possible that memory fragmentation caused by the nodejs runtime could result in heap growth until there was enough spare memory to make up for the fragmentation.

After 14 minutes the nodejs process was still using only 2MB out of its 21MB heap, like when it started. (14 because the 15-min run was paused for 1:09)

Here's the growth over 2.46 million http calls (showing only the heapTotal changes and final. The final memory footprint is reached after 4 minutes, and does not change for the next 11 min):

2014-12-03T04:52:48.358Z { rss: 12222464, heapTotal: 7130752, heapUsed: 1751228 }
2014-12-03T04:52:55.182Z { rss: 17326080, heapTotal: 9227904, heapUsed: 2186528 }
2014-12-03T04:53:59.488Z { rss: 21172224, heapTotal: 13422208, heapUsed: 2092796 }
2014-12-03T04:56:58.897Z { rss: 29556736, heapTotal: 21810816, heapUsed: 2100000 }
(... was paused for 1:09 around 05:02:27)
2014-12-03T05:07:45.598Z { rss: 29446144, heapTotal: 21810816, heapUsed: 2138608 }

My (slightly modified) test:

var ncalls = 0;
var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
  if (ncalls++ % 100000 === 0) {
    global.gc();
    console.log(new Date().toISOString(), process.memoryUsage());
  }
}).listen(3000, '127.0.0.1');
console.log("Listening on 3000...");
like image 156
Andras Avatar answered Oct 29 '22 17:10

Andras