2014-12-19 242 views
0

我有守護程序和perl上的子項。爲了守護進程我使用Proc::Daemon。控制守護進程和連接到DB的子進程(DBI lib),孩子們也通過imap(Mail::IMAPClient庫)收集郵件。 I undef兒童代碼中的所有變量,但隨着時間的推移,比任何人工作都更多的孩子會消耗大量內存。 ps輸出:如何在Perl中釋放內存

user 16521 0.6 1.6 135560 16516 ?  S 10:47 0:54 perl remote_imap.pl 
user 16523 0.2 20.0 331976 201764 ?  S 10:47 0:21 perl remote_imapd.pl 16521 
user 16525 0.1 3.0 157792 30720 ?  S 10:47 0:09 perl remote_imapd.pl 16521 
user 16527 0.1 3.0 157796 30704 ?  S 10:47 0:08 perl remote_imapd.pl 16521 
user 16529 0.1 3.0 157796 30572 ?  S 10:47 0:09 perl remote_imapd.pl 16521 
user 16531 0.1 3.0 157792 30612 ?  S 10:47 0:08 perl remote_imapd.pl 16521 

睡眠我使用usleepTime::HiRes庫。在remote_imap.pl usleep(100000),在remote_imapd.pl - usleep(500000)

爲什麼不釋放內存,因爲我爲所有變量(除了id_connet到DB)做了andef?如果你想,我會添加代碼。

主要守護 remote_imap.pl 兒童 remote_imapd.pl

+2

添加*最小*代碼足以重現問題。 – 2014-12-19 11:29:57

+1

Yup需要看到代碼才能理解首先分配內存的位置。 – 2014-12-19 11:30:51

+0

我添加超鏈接 – user3751471 2014-12-19 11:37:36

回答

2

Perl使用引用計數來管理它的內存空間。當你聲明一個變量時,一小部分被放在一邊。當你使用它時,會佔用更多的內存。一旦變量不再被引用,Perl可以重用內存空間。

這就是爲什麼保持詞法作用域很小並避免全局變量非常重要的原因 - 即使全局變量只在一次使用中,整個代碼範圍內的全局變量也是如此。

該問題是循環引用。一個循環引用永遠不會成爲未被引用,所以Perl不能自動'釋放'它。對於內部對象最終也很容易 - 如果對象的一部分具有對對象另一部分的引用。

這就是爲什麼你有像weaken()的東西。

我將在例子說明你上面給 - 子進程(你怎麼叫這些文件是一回事嗎?)你詞法範圍:

my (@array, @is_ok, @params, $user_id, $user_remote_id, $is_delete, $error_count, $is_first, $server, $port, $login, $password, $is_ssl, $no_error, $error_text, $pid, $date, $date_up, $exists, $q, $sth, $rv); 

外面你while循環,並試圖以'整理':

(@array, @is_ok, @params, $user_id, $user_remote_id, $is_delete, $error_count, $is_first, $server, $port, $login, $password, $is_ssl, $no_error, $error_text, $pid, $date, $date_up, $exists, $q, $sth, $rv) = undef; 

出於興趣 - 你爲什麼要這樣做?你不能把它們放在你的while循環中,然後你就不需要重用它們了嗎?我不知道這肯定是你的問題 - 它可能很容易在你導入的一個庫中。事實上,這與繁忙的孩子發生的事實意味着每個循環都有一些東西正在到達一個持久的數組或對象。

+0

我不記得在哪裏,但是我讀過使用全局變量並且在'while'的每個循環執行andef,在使用局部變量之前更好。但結果是一樣的。如果需要,我可以將所有代碼添加到Lib.pm中。 – user3751471 2014-12-19 12:48:40