从未在节点js中释放使用过的内存。 很奇怪

我刚刚完成开发我的第一个node.js应用程序,现在我正在testing它在我的VPS。 观察进程“节点”资源的使用情况,我注意到当请求一个页面(特别是一些页面)时,内存使用量的增加。 特别是,如果请求的页面是一个静态页面,增加是最小的。 如果请求的页面是/ admin,增加可以是1mb! 当然,当/ admin请求时,我的服务器比静态页面服务更多。 他连接到mongodb,他执行4“查找”,他绑定结果到一个HTML模板使用绑定 。 现在有什么问题? 这个记忆使用,将永远不会被释放! 所以我认为在我的代码中有一个逻辑错误,但后来我做了另一个更有趣的testing。

考虑一下这个非常简单的nodejs服务器:

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'); 

如果我试图用浏览器发出多个请求(简单地通过按住f5一分钟),内存使用增长缓慢,即使经过很长时间和closures浏览器之后,进程使用的内存也不会释放。 现在,在我的/pipe理代码中可能会出现一些错误(使用了1MB的内存,并且从未释放每个请求都非常高!),但是我认为上面的简单脚本使用的内存永远不会释放! 你怎么看待这件事? 有一种方法可以避免它?

另外,(在我的真实服务器),我用你的方式使用memwatch :

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

如果我用浏览器执行多个请求,大约10秒钟后,我正在做,过程将退出,这是错误的:

 { 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' } 

这是什么意思?? 这似乎与垃圾收集器有关! 我知道在这里粘贴我的/pipe理代码会更好,但是代码片段很长,并且与全局variables有关,所以如果没有200行的副本就不可能理解:D。 如果你需要更多的信息,我会给你!

节点没有释放内存并不奇怪,大多数程序不会。 他们很贪心:如果他们不够用,他们会从系统中获得更多的记忆。 如果他们有额外的,他们保留它以后。

短样本服务器不泄漏内存。 我用节点v0.10.29跑了14分钟的testing; 内存使用只能在最初缓慢增长,然后停止。 每个http调用的增长速度都小于1位,所以它不能在调用本身中泄漏内存。 由nodejs运行时引起的内存碎片可能会导致堆增长,直到有足够的备用内存来弥补碎片。

在14分钟之后,nodejs进程仍然只使用其21MB堆中的2MB,就像启动时一样。 (14分,因为15分钟的比赛暂停了1:09)

这里有超过246万个http调用的增长(只显示heapTotal的变化和最终的结果,最终的内存占用是在4分钟后达到的,在接下来的11分钟内不会改变):

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}
(…在05:02:27左右暂停了1:09)
2014-12-03T05:07:45.598Z {rss:29446144,heapTotal:21810816,heapUsed:2138608}

我的(稍加修改)testing:

 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...");