私はそのヒープを継続的に成長させる次のプログラムを持っています。これは、SyntaxError
を介して外部ファイル()を繰り返しロードする非常に単純なプログラムrequire
です。外部モジュールは、構文エラーのためにロードに失敗します。
ノードのガベージコレクターを実行し、ヒープサイズをダンプして、メモリがリークしていないかどうかを確認します。外部ファイル(SyntaxError.js
)の構文エラーを修正すると、リークはなくなり、メモリ使用量は100万回の反復後も一定に保たれます。
ノードバージョンの使用:0.10.29と --expose-gc
何が起こっているのか、そしてどうすればmemリークを回避できるのかについての洞察をいただければ幸いです。
テストコード:
(function() {
var MAX_ITER_COUNT, MEGABYTE, dumpMem, gc, iterCount, noop, peakMem, test2;
iterCount = 0;
MAX_ITER_COUNT = 1000 * 1000;
peakMem = 0;
MEGABYTE = 1024 * 1024;
noop = function() {};
dumpMem = function() {
var currentMem;
currentMem = Math.round(process.memoryUsage().heapUsed / MEGABYTE);
if (currentMem > peakMem) {
peakMem = currentMem;
}
return console.log("" + iterCount + " - memory is: " + currentMem + "/" + peakMem + " MB");
};
gc = function() {
return global.gc();
};
process.on("uncaughtException", function(err) {
return console.log("Unhandled exception! ", err, err.stack);
});
test2 = function() {
var e;
iterCount++;
try {
/*
Load a module that has a syntax error to create mem leak, and ignore exception
*/
require("./SyntaxError");
} catch (_error) {
e = _error;
}
gc();
dumpMem();
return setTimeout(test2, 0);
};
test2();
}).call(this);
そしてSyntaxError.js:
(function() {
'use strict';
/* y does not exist, and results in exception*/
var x;
x = y;
}).call(this);
これはノードのバグのようです。SyntaxError.js内のSyntaxError.jsの本体の周りにtry / catchを配置することで、これを回避できます。上記から簡略化した私のテスト:
mem-leak-bug.js:
for (i=0; i<1000000; i++) {
try {
require('./mem-leak--error.js');
}
catch (e) { }
if (i % 1000 === 0) {
global.gc();
console.log(i, process.memoryUsage().heapUsed/1e6|0, process.memoryUsage().heapTotal/1e6|0);
}
}
mem-leak--error.js:
注:catchブロックには明示的なリターンが必要です。そうでない場合、これもメモリリークになります。
// throw an undefined variable exception
try {
return x;
}
catch(e) {
return;
}
try-catchがないと、メモリリークが発生します。
% node --expose-gc ar/mem-leak-bug.js
0 1 5
1000 2 14
2000 2 14
3000 3 14
4000 3 23
5000 3 23
6000 4 24
SytaxError内のtry-catchでは、次のことは行われません。
% node --expose-gc ar/mem-leak-bug.js
0 1 5
1000 1 7
2000 1 7
3000 1 7
4000 1 7
5000 1 7
6000 1 7
7000 1 7
8000 1 7
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加