我在perl上有带孩子的守护进程。对于守护进程,我使用Proc::Daemon
。控制守护进程和连接到DB(DBI
lib)的子进程,子进程也通过imap(Mail::IMAPClient
lib)收集邮件。我undef
儿童代码中的所有变量,但随着时间的推移,一个工作比任何人都多的孩子会消耗大量的内存。 ps
输出:
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
for sleep我使用来自usleep
lib的Time::HiRes
。在remote_imap.pl usleep(100000)
中,在remote_imapd.pl
- usleep(500000)
中。
为什么不释放内存,因为我为所有变量{id_connet到DB除外} andef
?如果你愿意,我会添加代码。
主守护进程 remote_imap.pl 儿童 remote_imapd.pl
答案 0 :(得分: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循环中,然后您不需要重复使用它们?我不知道这一定是你的问题 - 它很容易出现在你导入的一个库中。与繁忙的孩子一起发生这一事实意味着每个循环都会变成一个持续存在的数组或对象。