2014-01-16 37 views
17

我已經使用我的node.js應用程序進行了一些測試,查找我的代碼應該執行的內存泄漏。我運行的腳本,在我看來應該泄漏內存,但我驚訝的結果。Node.js(v8)垃圾收集器如何工作?

redisClient.on('message', initRequest); 


function onSuccess(self, json){ 

    console.dir(json); 

} 


function initRequest(channel, message){ 

    var request = new RequestObject({ 

    redisMessage: message 

    }); 

    request.on('success', onSuccess); 

} 

redisClient每秒發出幾個'消息'事件。這意味着initRequest函數經常被調用。每次在內存中創建對象request,並且函數onSuccess綁定到其「成功」事件。

我認爲(但這裏我可能是錯的),只要有聽衆(在這種情況下爲onSuccess)綁定到這個對象,它不能被垃圾收集。然後我想,內存使用量會增長,因爲內存不會被釋放。

作爲此潛在泄漏的解決方案,我想使用.once而不是.on,因爲這樣可以解除偵聽器和對象的垃圾回收。

我用PMAP來測試這兩種情況(比較.on.once和一個另一種情況是不值得在這裏提到),我還沒有發現有很大的不同。

enter image description here

總之我有2個問題:

  1. 這是正常的GC行爲,清理內存在某些時間間隔,或之後達到一些threashold而不是連續清洗?

  2. 我是否正確地假設.on示例代碼應該泄漏內存,至於內存消耗圖上沒有看到?

+1

有些想法......對於第一個問題,是的,這是正常的。垃圾收集按週期運行。當你不再引用某些內存時,它可以被垃圾收集,但沒有跡象表明什麼時候會發生。至於第二個問題,我也希望有一個內存泄漏。看看爲什麼它在圖表中不可見的答案。 – Tibos

+0

爲了清楚起見,您可以使用.once顯示代碼嗎?我假設你在redisClient上做過,但現在只是猜測。另外,我確實在1中看到了更高的使用率。紅線......是「泄漏」?傳奇會很好。由於onSuccess在所有initRequest之間共享,因此將使用極少的額外內存,因此如果您的請求在達到幾百萬之前完成,我不會期望有更高的峯值。 – Spork

+0

您使用了哪個redis客戶端模塊?我搜索了'RequestObject'並沒有什麼意思。 – shawnzhu

回答

5

1:是:-)

2:在一般使用事件偵聽器當所述的存儲器泄漏是正在監聽從收集的垃圾,因爲被髮射的目的是保持防止對象對它的引用。

因此,在您的代碼中,onSuccess函數將引用您的request對象。然而,那個onSuccess只是一個被重用作所有請求對象的偵聽器的函數,所以不應該導致內存堆積。

旁註:我不知道redisClientRequestObject內臟但對我來說也像在request將盡快initRequest函數完成準備進行垃圾回收,這可能是任何聽衆的被稱爲前。

+0

看來,我的觀點來自於誰在引用誰的錯誤假設。現在我明白事件發起者正在引用監聽器,而不是相反的方式。 –

2

據我所見,請求對象應該只存在於initRequest函數中,並且應該在函數終止時標記爲垃圾回收。