1. 程式人生 > >node 閉包記憶體釋放

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%以上,並且一直存在不會釋放。

最後得出結論,當函式裡面存在內部函式,則形成閉包機制,活動環境中產生的一切變數都會儲存在記憶體中不會釋放。不管該內部函式是否被外部變數引用。