node 閉包記憶體釋放
最近在使用node做遊戲伺服器架構,其非同步回撥機制對處理大批量請求非常有效,而且避免了多執行緒造成的理解困難,死鎖等一系列問題。
伺服器在外網放了兩個星期,一次都沒掛過,確實很穩定。
但好事不長,遊戲上線之前開始做壓力測試,當併發數量達到500個時,記憶體直接達到70%以上,cpu達到100%,導致程式直接崩潰。
node不是有垃圾回收機制嗎?怎麼還會產生記憶體洩漏的問題。
後來經過仔細調查,發現是閉包造成的記憶體洩漏。因為閉包保留了對其作用域內的東西的引用,而這正是通常的記憶體洩露之源。
好了,舉個例子。
//第一種情況,變數在外層函式,內層函式引用外層函式的變數。內層函式並沒有被全域性變數引用,只是執行。
function aa(c)
{
var ads={};//變數在回撥函式外部
for(var i=0;i<20000000;i++)
{
ads[i]=i;
}
c(ads);
}
function bb()
{
var num=200;
aa(function(arr){
console.log(ads[1]);
})
}
bb();
setInterval(function(){},1000);//使用定時器保持程序一直在執行狀態
在Linux上測試發現,記憶體使用率達到10%以上,並且一直存在不會釋放。當執行bb函式是,其內部的函式傳入了匿名函式,形成了函式內部存在函式的機制,即閉包。該匿名函式引用了外部函式的變數ads。
//第二種情況,變數在回撥函式(內層函式)內部。
function aa(c)
{
c();
}
function bb()
{
aa(function(){
var ads={};//變數在回撥函式內部
for(var i=0;i<20000000;i++)
{
ads[i]=i;
}
})
}
bb();
setInterval(function(){},1000);//使用定時器保持程序一直在執行狀態
同樣,在Linux上測試發現,記憶體使用率達到10%以上,並且一直存在不會釋放。
//第三種情況,變數在外層函式,但內部函式並不執行。
function aa(c)
{
var ads={};//變數在回撥函式內部部
for(var i=0;i<20000000;i++)
{
ads[i]=i;
}
}
function bb()
{
aa(function(){
})
}
bb();
setInterval(function(){},1000);//使用定時器保持程序一直在執行狀態
同樣,在Linux上測試發現,記憶體使用率達到10%以上,並且一直存在不會釋放。
最後得出結論,當函式裡面存在內部函式,則形成閉包機制,活動環境中產生的一切變數都會儲存在記憶體中不會釋放。不管該內部函式是否被外部變數引用。