2012-11-28 46 views
2

我對抗我的節點服務器一個問題,我得到的是使節點應用崩潰的錯誤:瞭解Node.js的駐留集大小與堆大小(OOM錯誤)

FATAL ERROR: JS Allocation failed - process out of memory 

我使用nodetime來查看內存使用情況。我想也許我正在縮小這個問題,但我仍然很困惑。查看這個函數,它使用Mongoose從MongoDB加載緩存的對象:

StreamCache.prototype.loadCachedStream = function(_id, callback) 
{ 
    this.model.findOne({'_id': _id}, {'objects':1,'last_updated':1}, function(err, d){ 
     callback(err, d ? d.toObject() : null); 
     //The toObject() seems to cause the RSS to move into heap...? 
    }); 
}; 

注意到註釋行。昨晚晚上11點之前,這條線只是

callback(err,d); 

我昨晚在晚上11點加了toObject()調用。

現在看我的記憶圖表:

enter image description here

注意這個變化之前,RSS增長,但不是堆。更改後,堆和RSS增長完全相同(直到應用程序崩潰)。請注意,內存不足錯誤(以上)在更改之前和之後都發生了。然而,這個改變似乎已經使得堆大小在其泄漏到RSS大小之前相關,在堆大小之前(ish)。

我的假設是,出於某種原因,這意味着toObject()函數將泄露的數據從RSS移動到堆中,所以不僅RSS是泄漏的,而且堆也是。

這聽起來沒錯嗎?

如果是的話......任何想法可能會導致這個問題?

+0

您是否嘗試在啓動時和泄漏時間比較堆快照?它揭示了什麼嗎?在Nodetime中,您可以保存第一個快照(呃,現在就截圖或保存html),以便將其與漏洞時間快照進行直觀比較。注意:使用堆快照可能會使進程使用的內存增加一倍。 – logix

回答

0

我認爲堆/ RSS關聯與您遇到的內存不足問題無關。

(兩者之間有什麼區別嗎?一個是使用的虛擬內存總量,另一個是物理RAM中的內容,這種情況下,這意味着更改引入了數據結構,即操作系統(OS)已決定保留在物理RAM中很重要,例如因爲它們經常被訪問)

你說的問題的原因是在d.toJSON()調用中,爲什麼你認爲這對於jSON( )單獨不會導致內存不足錯誤?

如果「d」對象非常龐大,說它是大對象樹的根,當它被反序列化到JSON字符串中時它會消耗所有內存?

+0

Mongoose的「toJSON()」函數實際上並不將對象轉換爲JSON字符串;事實上,它減小了對象的大小(請參閱文檔)。 「d」對象是一個文檔,並且toJSON()函數的結果是適合稍後輸出的標準對象。因此,我很困惑你的意思是「toJSON()單獨...」只能在Mongoose文檔上調用JSON ... –

+0

我改變了我的問題,使用「toObject」而不是「toJSON」,因爲它們是在這種情況下在Mongoose中實際上是類似的,「toObject」是更清晰的命名法。另外 - 我的觀點是,由於這種變化導致堆與RSS相關,所以這個對象是泄漏對象似乎是合乎邏輯的結論(我並不關心RSS與堆本身,而只是關心什麼對象泄漏,爲什麼)。 –

+0

你是正確的我關於返回json字符串的調用的錯誤是錯誤的,但我仍然認爲toJSON或toObject可能是罪魁禍首,因爲它試圖創建pojo,可能序列化文檔中存在的所有屬性的返回結果,但可能在訪問時使用延遲實例化。在這裏,您將瀏覽文檔的每個單獨的道具併爲其實例化一個String值。沒有? – 1054211