【问题标题】:NodeJS 0.3.1 app leaking memoryNodeJS 0.3.1 应用程序泄漏内存
【发布时间】:2011-06-28 06:08:41
【问题描述】:

我有一个相当简单的 NodeJS 应用程序,它只是一个 shell,它接受请求并使用 Readability 形式解析内容(基于 https://github.com/arrix/node-readability)。问题是我注意到应用程序泄漏了内存——我已经运行了node --trace-gc,并且内存随着每个请求而慢慢积累,偶尔 gc 传递什么也不做。

$ node --trace-gc server.js 
Scavenge 2.3 -> 2.3 MB, 1 ms.
Mark-sweep 3.5 -> 2.9 MB, 2 ms.
Scavenge 4.4 -> 3.8 MB, 0 ms.
16 Feb 10:57:51 - Server started on PORT 8000
Scavenge 5.9 -> 5.0 MB, 2 ms.
Mark-sweep 5.0 -> 4.2 MB, 3 ms.
Mark-compact 4.2 -> 4.1 MB, 7 ms.
Scavenge 5.2 -> 4.7 MB, 1 ms.
Scavenge 5.5 -> 5.1 MB, 1 ms.
Scavenge 5.9 -> 5.5 MB, 1 ms.
Scavenge 7.1 -> 6.3 MB, 2 ms.
Scavenge 7.8 -> 7.0 MB, 2 ms.
Mark-sweep 8.5 -> 7.6 MB, 10 ms.
Scavenge 11.7 -> 9.7 MB, 4 ms.
Scavenge 12.7 -> 11.2 MB, 5 ms.
Mark-sweep 14.2 -> 12.4 MB, 21 ms.
Scavenge 20.5 -> 16.5 MB, 10 ms.
Scavenge 22.5 -> 19.5 MB, 11 ms.
Mark-sweep 25.5 -> 22.4 MB, 38 ms.
Scavenge 36.6 -> 29.6 MB, 25 ms.
Scavenge 41.6 -> 35.6 MB, 24 ms.
Mark-sweep 46.8 -> 41.1 MB, 75 ms.
Scavenge 46.8 -> 44.0 MB, 33 ms.
Mark-sweep 57.2 -> 50.6 MB, 92 ms.
Scavenge 62.3 -> 56.5 MB, 26 ms.
Scavenge 68.5 -> 62.6 MB, 24 ms.
Scavenge 74.6 -> 68.6 MB, 26 ms.
Mark-sweep 80.6 -> 74.5 MB, 130 ms.
Scavenge 80.5 -> 77.6 MB, 25 ms.
Mark-sweep 77.6 -> 77.4 MB, 112 ms.
Mark-compact 77.4 -> 77.4 MB, 260 ms.

即使在请求停止并且 GC 有时间反复运行之后,内存使用量也不会减少。

我或多或少确信我必须在某处分配一个全局变量,但我不知道如何修复它。该项目的代码位于此处:

https://github.com/erskingardner/Readable

有人对我应该做什么有任何建议(和推理)吗?

【问题讨论】:

  • 0.3.1 不稳定,0.4.0 已经发布。你试过吗?
  • 感谢各位的建议——我确实在我的开发机器上更新到了 0.4.0(服务器已经在 0.4.0 上)——但这并没有帮助。请参阅下面的答案。

标签: memory memory-leaks node.js


【解决方案1】:

我会在这里回答我自己的问题,希望它可以帮助其他有同样问题的人。

问题实际上与我在创建服务器时使用的 event.emitter 相关。当只使用一个连接时,没有内存泄漏(想想开发),但是当应用程序开始受到攻击时,大量内存开始爬升,而 GC 没有做任何事情。我在链中放置了一个事件监听器太高了一步,因此我正在创建一个永远不会被破坏的事件监听器。

==

破解密码

Readable.prototype.createHTTPServer = function() {
  var self = this;

  var server = http.createServer(function(request, response) {  
    request.addListener('end', function() {
      var  location  = url.parse(request.url, true)
          ,params    = (location.query || request.headers)
          ,body      = "";

      if (location.pathname == '/' && request.method == "GET"){
        if (params["url"] == null){
          response.writeHead(200, {
            'Content-Type': 'text/html'
          });
          response.end("Good to go, you might want to try adding a url param though.");
        }
        else if (params["url"] != null){
          self.fetchAndParse(params["url"], params);
        }
        var listener = emitter.on("readability", function(result) {
          response.writeHead(200, {
            'Content-Type': 'text/html'
          });
          if (result == "error"){
            response.end("error");
          } else {
            response.end(result.content);          
          }
        });
      }
    });
  });
  return server
};

监听器变量是永远不会被破坏的部分。我试图强制删除变量,但响应从未到达浏览器。答案是我所要做的就是在else if 语句中移动那个监听器变量,当函数完成运行时它会自动被GC'ed。

==

正确代码

Readable.prototype.createHTTPServer = function() {
  var self = this;

  var server = http.createServer(function(request, response) {  
    request.addListener('end', function() {
      var  location  = url.parse(request.url, true)
          ,params    = (location.query || request.headers)
          ,body      = "";

      if (location.pathname == '/' && request.method == "GET"){
        if (params["url"] == null){
          response.writeHead(200, {
            'Content-Type': 'text/html'
          });
          response.end("Good to go, you might want to try adding a url param though.");
        }
        else if (params["url"] != null){
          self.fetchAndParse(params["url"], params);
          var listener = emitter.on("readability", function(result) {
            response.writeHead(200, {
              'Content-Type': 'text/html'
            });
            if (result == "error"){
              response.end("error");
            } else {
              response.end(result.content);          
            }
          });
        }
      }
    });
  });
  return server
}; 

【讨论】:

    【解决方案2】:

    就像 PartlyCloudy 提到的,你真的应该将你的 node.js 实例更新到最新最好的 v0.4.0。希望该错误已得到修复,或者如果没有,您可以在 github 上提交 issue

    我认为 Ryan's 不会修复旧的不稳定版本的任何错误。

    【讨论】:

      猜你喜欢
      • 2018-11-12
      • 1970-01-01
      • 2016-04-22
      • 2016-03-28
      • 2010-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多