2012-09-18 31 views
0

我有2個函數用於清除和搜索數組。這是微不足道的東西。我注意到在某些情況下,對於超過100個元素的數組,當使用這些函數時會發生巨大的內存泄漏,並且我的node.js JavaScript應用程序將會死亡。爲什麼反序列化我的目標數組的序列化副本修復了mem泄漏問題?

什麼可能是「錯誤」與我的數組ARR,這將意味着反序列化它的序列化版本修復了MEM泄漏?爲什麼反序列化我的目標數組的序列化副本修復了mem泄漏問題?

可能相關:

ARR是建立與幾十調用Concat的。

搜索功能:

function findObjInArray(arr, obj, lookupKeyChain){ 
    var tmpObj = undefined; 
    for(var i = 0; i < arr.length; i++){ 
     tmpObj = arr[i]; 
     for(var j = 0; j < lookupKeyChain.length; j++){ 
      tmpObj = tmpObj[lookupKeyChain[j]] 
      if(!tmpObj){ 
       break; 
      }else if(j==lookupKeyChain.length-1){ 
       if(tmpObj==obj){ 
        return arr[i]; 
       } 
      } 
     } 
    } 
    return undefined; 
} 

的重複數據刪除功能:

function combineProducts(productList, idKey){ 
    var deDupedProducts = [] 
    for(var i = 0; i < productList.length; i++){ 
     var precedent = findObjInArray(deDupedProducts, productList[i][idKey], [idKey]); 
     if(precedent){ 
      //just add tag data to precedent 
      for(var j = 0; j < productList[i].tags.length; j++){ 
       precedent.tags.push(productList[i].tags[j]); 
      } 
     }else{ 
      deDupedProducts.push(productList[i]); 
     } 
    } 
    return deDupedProducts; 
} 

在ARR結構的一個例子:

[ 
     { 
      "price": "$9.99", 
      "name": "Big Widgets", 
      "tags": [ 
       { 
        "tagClass": "Category", 
        "tagName": "On Sale" 
       } 
      ] 
     }, 
     { 
      "price": "$5.00", 
      "name": "Small Widgets", 
      "tags": [ 
       { 
        "tagClass": "Category", 
        "tagName": "On Sale" 
       }, 

      ] 
     }, 
     ... 
    ] 

引起MEM泄漏的呼叫:

combineProducts(
    arr, 
    "name" 
) 

是固定的問題,並給了我正確的結果召喚:

combineProducts(
    JSON.parse(JSON.stringify(arr)), 
    "name" 
) 
+0

哪裏出錯,或泄漏的證據? – OrangeDog

+0

錯誤是一條消息,如FATAL錯誤,內存不足。漏洞的證據是在Mac OS X活動監視器中節點進程的Real Mem值徘徊在50MB左右,直到在調用combineProducts期間,它在大約20秒內爬升到1.3GB,然後應用程序失敗並顯示錯誤。我現在沒有手邊的確切錯誤文本的副本。 – Trindaz

+0

Node.JS被垃圾收集。如果您不允許GC運行,則內存使用量增加通常不代表泄漏。 – OrangeDog

回答

1

無關,而是基於對象的算法是大名單比你不斷擴展的線性搜索更有效(和簡潔) 。

function combineProducts(productList, idKey) { 
    var lookup = {}; 

    productList.forEach(function(product) { 
     var precedent = lookup[product[idKey]; 

     if (precedent) { 
      precedent.tags = precedent.tags.concat(product.tags); 
     } 
     else { 
      lookup[product[idKey]] = product; 
     } 
    }); 

    return Object.keys(lookup).map(function(idValue) { 
     return lookup[idValue]; 
    }); 
} 

只有你的功能不同的是,順序是不保留(不過,如果該數據是由idKey下令開始,一單通算法將是更好)。