Skip to content

Instantly share code, notes, and snippets.

@you21979
Last active January 4, 2018 18:00
Show Gist options
  • Save you21979/97fd5a5d3a23ce6e9a5b to your computer and use it in GitHub Desktop.
Save you21979/97fd5a5d3a23ce6e9a5b to your computer and use it in GitHub Desktop.
起きる!メモリーリーク(javascriptクロージャー編)

メモリリークは起きない

var hoge = function(){
    var x = 0;
    return function(){
        return x++;
    }
}
var h = hoge();
console.log(h());
console.log(h());
console.log(h());

依存しているhの参照が切れた段階でxはガベージコレクタの対象になる

メモリリークは起きる

var hoge = function(){
    var x = 0;
    process.on('exit', function(){
        x++;
    });
    return function(){
        return x;
    }
}
var h = hoge();
console.log(h());
console.log(h());
console.log(h());

依存しているhの参照が切れた段階ではxはガベージコレクタの対象にならない
xがnode.jsが動いている限りずっと破棄されないprocessオブジェクトから参照され続けるため。

クロージャーの中でイベントハンドラを登録するときは慎重に。

わかりやすい事例としてsetTimeoutで実行してみる

var leak = function(){
    var x = 0;
    process.on('exit', function(){
        x++;
    });
    return function(){
        return x;
    }
}
var update = function(){
    var h = leak();
    setTimeout(update, 0);
}
update();

node.jsのEventEmitterはデフォルトで10件までしか登録できないようになっているので それを超えるとワーニングが出る。

(node) warning: possible EventEmitter memory leak detected. 11 listeners added. Use emitter.setMaxListeners() to increase limit.
Trace
    at process.addListener (events.js:160:15)
    at process.on.process.addListener (node.js:773:26)
    at leak (leak.js:9:13)
    at update [as _onTimeout] (leak.js:17:13)
    at Timer.listOnTimeout [as ontimeout] (timers.js:110:15)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment