jsdom和node.js泄漏内存

时间:2012-12-15 14:43:20

标签: node.js memory-leaks jsdom

我找到了一些提到类似问题的人的答案总是如此,确保你在完成后调用window.close()。然而,这对我来说似乎没有用(节点0.8.14和jsdom 0.3.1)

一个简单的复制品

var util = require('util');
var jsdom=require('jsdom');

function doOne() {
  var htmlDoc = '<html><head></head><body id="' + i + '"></body></html>';
  jsdom.env(htmlDoc, null, null, function(errors, window) {
    window.close();
  });
}

for (var i=1;i< 100000;i++ )  {
  doOne();
  if(i % 500 == 0)  {
    console.log(i + ":" + util.inspect(process.memoryUsage()));
  }
}
console.log ("done");

我得到的输出是

500:{ rss: 108847104, heapTotal: 115979520, heapUsed: 102696768 }
1000:{ rss: 198250496, heapTotal: 194394624, heapUsed: 190892120 }
1500:{ rss: 267304960, heapTotal: 254246912, heapUsed: 223847712 }
...
11000:{ rss: 1565204480, heapTotal: 1593723904, heapUsed: 1466889432 }

此时风扇变得疯狂,测试实际上停止了......或者至少开始非常缓慢

是否有任何其他提示而不是w​​indow.close来摆脱内存泄漏(或者它确实看起来像内存泄漏)

谢谢!

彼得

5 个答案:

答案 0 :(得分:10)

使用jsdom 0.6.0来帮助抓取一些数据并遇到同样的问题 window.close只能帮助减缓内存泄漏,但它最终会逐渐消失,直到进程被杀死。

使用运行脚本 node --expose-gc myscript.js

在修复内存泄漏之前,除了调用window.close之外,手动调用垃圾收集器似乎也有效:

if (process.memoryUsage().heapUsed > 200000000) { // memory use is above 200MB
    global.gc();
}

在调用window.close后被困住了。每次触发时,内存使用会立即回落到基线(对我来说大约50MB)。几乎感觉不到停止。

答案 1 :(得分:4)

您没有给程序任何空闲时间进行垃圾回收。我相信你会遇到同样的问题,任何大型对象图在一个没有中断的循环中被多次创建。

这可以通过CheapSteaks的回答来证实,它可以手动强制进行垃圾回收。如果可行的话,jsdom中不会有内存泄漏,因为根据定义,内存泄漏会阻止垃圾收集器收集泄漏的内存。

答案 2 :(得分:3)

我遇到了与jsdom相同的问题并切换到cheerio,这比jsdom快得多,即使扫描了数百个网站也能正常工作。也许你应该尝试一下。唯一的问题是,它具有你可以在jsdom中使用的所有选择器。

希望它也适合你。

丹尼尔

答案 3 :(得分:1)

gulp,内存使用,清理,变量删除,window.close()

var gb = setInterval(function () {

    //only call if memory use is bove 200MB
    if (process.memoryUsage().heapUsed > 200000000) { 
        global.gc();
    }

}, 10000); // 10sec


gulp.task('tester', ['clean:raw2'], function() {

  return gulp.src('./raw/*.html')
    .pipe(logger())
    .pipe(map(function(contents, filename) {


        var doc = jsdom.jsdom(contents);
        var window = doc.parentWindow;
        var $ = jquery(window);

        console.log( $('title').text() );

        var html = window.document.documentElement.outerHTML;

        $( doc ).ready(function() {
            console.log( "document loaded" );
            window.close();
        });

        return html;
    }))
    .pipe(gulp.dest('./raw2'))
    .on('end', onEnd);
});
对于7k文件,我的使用率在200mb到300mb之间。花了30分钟。 这可能对某些人有帮助,因为我用谷歌搜索并没有找到任何有用的东西。

答案 4 :(得分:0)

解决这个问题的方法是在分叉的 child_process 中运行与 jsdom 相关的代码,并在完成后发回相关结果。然后杀死 child_process。