繁体   English   中英

jsdom 和 node.js 内存泄漏

[英]jsdom and node.js leaking memory

我发现了一些对有类似问题的人的参考,答案总是如此,请确保在完成后调用 window.close() 。 但是,这似乎对我不起作用(节点 0.8.14 和 jsdom 0.3.1)

一个简单的repro

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 之外,有没有人有其他提示可以消除内存泄漏(或者它确实看起来像内存泄漏)

谢谢!

彼得

使用 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

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

这由CheapSteaks的回答证实,它手动强制垃圾收集。 如果可行的话,jsdom 中就不会出现内存泄漏,因为内存泄漏的定义会阻止垃圾收集器收集泄漏的内存。

我曾与jsdom和switcht同样的问题cheerio ,这是远远快于jsdom和偶数扫描数百个站点后的作品。 也许你也应该尝试一下。 唯一的问题是,它没有您可以在 jsdom 中使用的所有选择器。

希望它也适用于你。

丹尼尔

使用吞咽,内存使用,清理,变量删除,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分钟。 这可能对某人有帮助,因为我用谷歌搜索并没有找到任何有用的东西。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM