У приложения NodeJS 0.3.1 утечка памяти - PullRequest
1 голос
/ 16 февраля 2011

У меня есть довольно простое приложение NodeJS, которое представляет собой не что иное, как оболочку, которая принимает запросы и анализирует контент, используя форму 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

Есть ли у кого-нибудь какие-либо предложения (и аргументы) о том, что мне следует делать?

Ответы [ 2 ]

2 голосов
/ 18 февраля 2011

Я отвечу на свой вопрос здесь в надежде, что он может помочь другим людям с такой же проблемой.

Проблема на самом деле была в том, что я использовал 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
};

Переменная слушателя была той частью, которая никогда не уничтожалась. Я пытался принудительно удалить переменную, но затем ответ так и не попал в браузер. Ответ состоял в том, что все, что мне нужно было сделать, это переместить этот слушатель var в оператор else if, и он был автоматически обработан 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
}; 
0 голосов
/ 17 февраля 2011

Как уже упоминалось в PartlyCloudy, вам действительно следует обновить свой экземпляр node.js до последней версии v0.4.0.Надеюсь, ошибка была исправлена, или, если нет, вы можете отправить проблему на github.

Я не думаю, что Райан исправит какие-либо ошибки в этой старой нестабильной версии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...