2014-12-19 238 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