Used memory has never been released in node js. Very strange

I just finished developing my first node.js application, and now I'm testing it on my VPS. As I watched the resource usage of the "node" process, I noticed an increase in memory usage when a page is requested (especially some). In particular, if the requested page is a static page, the increase is minimal. If the requested page is / admin, the increase may be 1 Mb! Of course, when / admin is requested, my server does more than serve the static page. It connects to mongodb, it performs 4 "find", it binds the results to the html template using bind . Now what is the problem? This used memory will never be released! So I thought there was a logical error in my code, but then I made 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 several requests using the browser (just holding f5 for one minute), the 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 is likely that there is some error in my / admin code (1 mb of used memory and never released for every request, it is very high!), But I think it’s very strange that the memory used by the simple script above will be never released! What do you think about this? Is there any way to avoid this?

Also (on my real server) I used memwatch as follows:

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

If I execute several requests with a browser, after about 10 seconds I will do it, the process will end, and this will be an 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? This seems to be related to the garbage collector! I know that it would be better to insert my / admin code here, but the fragment is very long and associated with global variables, so it is impossible to understand without a copy of 200 lines: D. If you need more information, I will give you!

+5
source share
1 answer

Not surprisingly, node does not release memory; most programs do not. They are greedy: if they run, they get more memory from the system. If they have extra, they save it for later.

A short sample server does not leak memory. I conducted a 14 minute test using node v0.10.29; memory usage only grows slowly initially and then stops. The growth rate is less than one bit per HTTP call, so it cannot leak memory in the calls themselves. Perhaps the fragmentation of memory caused by nodejs runtime can lead to heap growth until there is enough spare memory to compensate for fragmentation.

After 14 minutes, the nodejs process still used only 2 MB from its 21 MB heap, for example when it was running. (14 because the 15 minute run was suspended at 1:09)

Here the growth amounted to more than 2.46 million http-calls (showing only changes in the heap and the end. The final memory size was reached after 4 minutes and does not change over the next 11 minutes):

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 suspended at 1:09 at about 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..."); 
+5
source

Source: https://habr.com/ru/post/1207743/


All Articles