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 イベントではなくメジャー GC イベントをトリガーした可能性があるためと思われます。- https://github.com/cypress-io/cypress/issues/350#issuecomment-688969443

于 2013-05-25T06:49:52.143 に答える
4

jsdom でも同じ問題が発生し、cheerioに切り替えました。これは jsdom よりもはるかに高速で、何百ものサイトをスキャンした後でも機能します。あなたも試してみるといいかもしれません。唯一の問題は、jsdom で使用できるすべてのセレクターがないことです。

それがあなたにとってもうまくいくことを願っています。

ダニエル

于 2012-12-16T13:46:37.117 に答える