I have daemon with children on perl. For daemonize i use Proc::Daemon
. Control daemon and children connected to DB(DBI
lib), childs collect mail via imap (Mail::IMAPClient
lib) too. I undef
all variables in code of children, but over time, a child who works more than anyone, consume a lot of memory. ps
output:
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 i use usleep
from Time::HiRes
lib. In remote_imap.pl usleep(100000)
, In remote_imapd.pl
- usleep(500000)
.
Why memory is not released, because I did andef
for all variables (except id_connet to DB)? If you want, I'll add code.
Main daemon
remote_imap.pl
Child
remote_imapd.pl
Perl uses reference counting to manage it's memory space. When you declare a variable, a small amount is set aside. When you use it, more memory is occupied. Perl may reuse the memory space once a variable is no longer referenced at all.
That's why it's quite important to keep lexical scopes small, and avoid global variables - something global is 'in scope' throughout your code, even if it's only used once.
The gotcha is circular references. A circular reference never becomes unreferenced, so perl can't 'release' it automatically. That's also fairly easy to end up with inside objects - if part of an object has a reference to another part of the object.
That's why you have things like weaken()
.
I'll note in the examples you give above - the child process (why did you call the files the same thing?) you've lexically scoped:
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);
Outside your while
loop, and tried to 'tidy up' by:
(@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;
Out of interest - why are you doing this? Could you not scope them within your while loop, and then you won't need to reuse them? I don't know that's necessarily your problem though - it could quite easily be in one of the libraries you import. The fact that it's happening with the busier child implies that each loop something is getting to an array or object that's persisting.