17

我发现了一些关于人们遇到类似问题的参考资料,但答案总是如此,请确保在完成后调用 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 }

在这一点上,风扇变得疯狂,测试实际上停止了……或者至少开始变得非常缓慢

除了 window.close 之外,还有没有人有任何其他提示来摆脱内存泄漏(或者它确实看起来像内存泄漏)

谢谢!

彼得

4

5 回答 5

14

使用 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)。几乎无法察觉的停顿。

更新:也考虑global.gc()连续调用多次而不是只调用一次(即global.gc();global.gc();global.gc();global.gc();global.gc();

多次调用 window.gc() 更有效(基于我不完美的测试),我怀疑它可能导致 chrome 触发一个主要的 GC 事件而不是次要的事件。- https://github.com/cypress-io/cypress/issues/350#issuecomment-688969443

于 2013-05-25T06:49:52.143 回答
6

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

CheapSteaks 的回答证实了这一点,该回答手动强制垃圾收集。如果可行,jsdom 中就不会存在内存泄漏,因为内存泄漏根据定义会阻止垃圾收集器收集泄漏的内存。

于 2013-09-10T12:51:37.967 回答
4

我在使用 jsdom 时遇到了同样的问题,然后切换到了chesterio,它比 jsdom 快得多,并且即使在扫描了数百个站点之后也能正常工作。也许你也应该尝试一下。唯一的问题是,它没有您可以在 jsdom 中使用的所有选择器。

希望它也适合你。

丹尼尔

于 2012-12-16T13:46:37.117 回答
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分钟。这可能对某人有帮助,因为我用谷歌搜索并没有发现任何有用的东西。

于 2014-12-16T23:38:41.370 回答
1

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

于 2021-04-28T23:57:42.127 回答