3

一个多月以来,我一直在为一个非常烦人的内存泄漏问题而苦苦挣扎,但我不知道如何解决它。

我正在编写一个基于 http、async、cheerio 和 nano 的通用网络爬虫。从一开始,我就一直在努力解决难以隔离的内存泄漏问题。我知道可以使用 Google Chrome 进行堆转储并对其进行分析,但我无法理解输出。它通常是一堆无意义的字符串和对象,导致一些匿名函数告诉我什么都没有(这可能是我缺乏经验)。

最终我得出一个结论,我当时使用的库(jQuery)有问题,我用 Cheerio 替换了它。我的印象是 Cheerio 解决了这个问题,但现在我确信它只会让它变得不那么引人注目。

您可以在以下位置找到我的代码:https ://github.com/lukaszkujawa/node-web-crawler 。我知道可能需要分析很多代码,但也许我正在做一些愚蠢的事情,这可能是显而易见的。我怀疑从多个“线程”(带有)执行 HTTP 请求的主代理类https://github.com/lukaszkujawa/node-web-crawler/blob/master/webcrawler/agent.js 。async.queue

如果您想运行它需要 CouchDB 的代码,然后npm install执行以下操作:

$ node crawler.js -c conf.example.json

我知道 Node 不会因为垃圾收集而发疯,但经过 10 分钟的大量爬网后,使用的内存很容易超过 1GB。

(使用 v0.10.21 和 v0.10.22 测试)

4

1 回答 1

5

对于它的价值,即使您实际使用的内存不是很大,Node 的内存使用量也会不断增长。这是为了代表 V8 引擎进行优化。要查看您的实际内存使用情况(以确定是否确实存在内存泄漏),请考虑将此代码(或类似代码)放入您的应用程序中:

setInterval(function () {
    if (typeof gc === 'function') {
        gc();
    }
    applog.debug('Memory Usage', process.memoryUsage());
}, 60000);

运行node --expose-gc yourApp.js。在强制垃圾回收之后,每分钟都会有一条日志行指示实际内存使用情况。我发现随着时间的推移观察它的输出是确定是否存在泄漏的好方法。

如果您确实发现了泄漏,我发现调试它的最佳方法是一次删除大部分代码。如果泄漏消失,请将其放回原处并消除一小部分。使用此方法将范围缩小到问题发生的位置。闭包是一个常见的来源,但也会检查其他任何可能无法清理的引用。许多网络应用程序将为不会立即销毁的套接字附加处理程序。

于 2013-11-14T22:20:37.717 回答