2012-10-20 140 views
8

我現在正在搜索關於此問題的2周,似乎我無法在網上搜索任何答案。線程中的Perl內存泄漏(線程不釋放內存)

所以,這裏是兩件代碼:

1:

#! /usr/bin/perl 

# 
# RELEASE MEMORY 
# 

use threads; 

my @child; 

$ii=0; 


while (1) 
{ 
    my @child = threads->new(\&test, "test"); 
    $_->detach for @child; 
    print "$ii\n"; 
    $ii++; 
} 

sub test { 
    my ($ee) = 0;  
} 

2:

#! /usr/bin/perl 

# 
# DO NOT RELEASE MEMORY 
# 

use threads; 

my @child; 

$ii=0; 


for($ii=0;$ii<2000;$ii++) { 
    my @child = threads->new(\&test, "test"); 
    $_->detach for @child; 
    print "$ii\n"; 
} 

while(1) 
{ 
    sleep(10); 
} 

sub test { 
    my ($ee) = 0;  
} 

所以這裏的問題。第一個代碼只運行一個無限循環,每次釋放內存到操作系統大約2秒(根據ps)

第二個代碼也是釋放內存,但只有當他在「for」循環內運行時。 一旦它退出for循環並進入無限循環,所有尚未釋放到for循環中的內存都不會釋放回操作系統。

是否有人遇到同樣的問題?

的Perl:(v5.16.1)建爲x86_64的Linux的線程多

OS:Debian的6.0.5

非常感謝


編輯1: 我用800線程並且全部通過打印$ ee var來驗證它們退出。

但是一旦進入while(1)循環,這裏是ps aux | grep perl輸出:

[email protected]:~# ps aux | grep perl 
root  6807 41.5 2.5 387780 209580 pts/0 S+ 16:38 0:02 /opt/ActivePerl-5.16/bin/perl /home/tttlast.pl 
root  7627 0.0 0.0 7548 856 pts/1 S+ 16:38 0:00 grep perl 

所以所有線程退出但內存使用率仍然是我的服務器總內存的2.5%。 所以除非我殺了程序,內存仍在使用中。


編輯2:

我解決我的問題,我改變了我的結構。實際上,主程序(長期運行的程序)已經分開,我使用小程序在所有線程完成退出之前等待。

這種方式它沒有滿虛擬內存和其他守護進程沒有被殺死。

感謝大家帶領我去那個解決方案。

+3

我試過他們在OS X 10.8/Perl 5.16.0。我看到的第一種行爲是在大約6兆的駐留數千線程後關閉內存使用級別。第二個級別在大致相同的水平,並保持在睡眠。線程內存顯然在兩種情況下都被釋放。你能否發佈更多證據表明記憶沒有被釋放?也許每秒都有'ps'輸出? – Schwern

+0

添加了ps輸出。事實上,真正的程序是更復雜的,只是沒有發佈在這裏,沒有被燒燬,但它運行了很長時間,每個小時打開大約250到900個線程,將內存填充到總內存的10%左右,從不釋放。但這與第二個例子完全相同。讓我知道你是否需要更多信息。謝謝 – user1761742

+1

糾正我,如果我錯了,但不Perl *只*當*進程*退出時的可用內存?這是一個長期存在的「特徵」,我無法找到有關最近perldeltas中的線程優化的任何證據。我更加驚訝於你聲稱目睹的內存使用量減少*而非「泄漏」。 – amon

回答

4

這裏沒有「問題」。這是所有正常的,預期的行爲。如果這給你帶來某種問題,你就沒有解釋它是什麼。

沒有理由將虛擬內存返回到操作系統,因爲虛擬內存不是稀缺資源。沒有理由將物理內存返回到操作系統,因爲操作系統無論如何都會有更好的使用方式。

沒有證據表明它是內存泄漏。測試結果表明,沒有任何情況下內存使用量沒有限制地增加 - 在所有情況下,它最終會平穩下來。

+0

剛剛覈實,你是對的。其他進程使用的內存在perl程序需要內存時採用。事實上這個問題是Perl的其他進程佔用內存會被終止,比如mysql和郵件服務器。而且perl程序使用mysql和郵件服務器來運行。我應該編輯我的文章還是張貼另一個問題?順便說一句,謝謝你 – user1761742

+1

你只是不應該創造這麼多的線程。這不明智。 –