2012-01-13 134 views
8

我看到下面的代碼中的內存泄漏:node.js文件內存泄露?

while (true) { 
    console.log("Testing."); 
} 

我試圖定義字符串,然後使用一個常數,但它泄漏內存,還是:

var test = "Testing."; 
while (true) { 
    console.log(test); 
} 

同樣的泄漏發生如果我使用一個文件,而不是標準的日誌:

var test = "Testing."; 
var fh = fs.createWriteStream("test.out", {flags: "a"}); 
while (true) { 
    fh.write(test); 
} 

我想也許這是因爲我沒有正確關閉文件,但我想這和s直到看到了泄漏:

var test = "Testing"; 
while (true) { 
    var fh = fs.createWriteStream("test.out", {flags: "a"}); 
    fh.end(test); 
    fh.destroy(); 
    fh = null; 
} 

沒有人有任何線索,以我應該如何寫的東西沒有內存泄露?

回答

10

發生這種情況是因爲您從不給節點處理「寫入成功」事件的機會,因此他們無止境地排隊。爲了給節點一個處理它們的機會,你必須讓事件循環不時做一次迭代。這不會泄漏:

function newLine() { 
    console.log("Testing."); 
    process.nextTick(newLine); 
} 
newLine(); 

在實際使用的情況下,這是沒有問題,因爲你幾乎從來沒有一次,這事寫出來的數據如此巨大的數額。如果是這樣,請不時循環事件循環。

但是,第二個問題也出現在nextTick技巧中:寫入是異步的,如果控制檯/文件/任何比節點慢的節點,節點都會無限地緩存數據,直到輸出再次釋放。爲了避免這種情況,在編寫一些東西之後,你必須聽取drain事件 - 它會告訴你什麼時候管道再次釋放。看到這裏:http://nodejs.org/docs/latest/api/streams.html#event_drain_

+0

我能夠通過文件處理程序('fs.createWriteStream')重現您的解決方案,但是如果我嘗試使用'console.log',仍然會發生內存泄漏。 'function writeConsole(){console.log(「test」); if(typeof(gc)==「function」)gc(); process.nextTick(writeConsole); } writeConsole();' 當用'node test.js'運行上面的代碼塊時,每次迭代都會看到我的內存使用情況。當我將它作爲'node --expose-gc test.js'運行時,我沒有看到任何不斷的增加。 – facetious 2012-01-13 23:40:10

+0

@facetious:它不經常進行GC循環,效率不高。讓它運行一段時間,你會發現內存使用最終會下降到開始的水平。 – thejh 2012-01-14 01:10:02

+0

@facetious:我甚至記得自己試驗過 - 我用gnuplot做了一個內存使用圖,如果我沒有記錯的話,它總是會有一段時間的增加,然後回落到接近開始值。 – thejh 2012-01-14 01:12:37