【问题标题】:Used memory never released in node js. Very strange使用的内存从未在节点 js 中释放。很奇怪
【发布时间】:2015-01-24 21:34:53
【问题描述】:

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

考虑这个非常简单的 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 一分钟),内存使用量会缓慢增长,并且进程使用的内存将永远不会释放,即使经过很长时间和关闭浏览器后也是如此。现在,很可能在我的 /admin 代码中存在一些错误(每个请求使用 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' }

这是什么意思??它似乎与垃圾收集器有关!我知道最好在这里粘贴我的 /admin 代码,但是 sn-p 很长并且与全局变量有关,所以如果没有 200 行的副本就无法理解:D。如果您需要更多信息,我会给您!

【问题讨论】:

  • 您是否尝试手动强制垃圾回收?检查devjar.me/post/22886448979/manually-run-gc-in-node-js:“使用标志--nouse_idle_notification 和--expose_gc 启动节点,然后当您要运行GC 时,只需调用global.gc()。”
  • 您可以在 gist / pastebin 中发布您的代码。但是您提到全局变量的简单事实应该会触发警报:) 我们确实需要更多信息。另外,尝试memwatch热代码,不要在启动后立即进行。
  • 我(Andras)用强制 gc 尝试了上面的代码,它非常非常渐进,但是发生了一些事情。超过 200 秒和 580,000 次调用 heapUsed 增加了 40KB(很小),但 heapTotal 增加了 12MB,先是 +4,然后是 +8。我现在跑步 5 分钟
  • 我收回了,我不再认为这是泄漏。在较长时间内,内存使用看起来很稳定。

标签: node.js memory-leaks


【解决方案1】:

节点不释放内存并不奇怪,大多数程序都不会。他们是贪婪的:如果他们用完了,他们会从系统中获得更多的内存。如果他们有多余的,他们会保留以备后用。

简短的示例服务器没有泄漏内存。我用节点 v0.10.29 进行了 14 分钟的测试;内存使用仅在最初缓慢增长,然后停止。每个 http 调用的增长率不到一位,因此它不会在调用本身中泄漏内存。由 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 }

我的(稍作修改)测试:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多