2014-12-19 3 views
0

У меня есть демон с детьми на perl. Для daemonize я использую Proc::Daemon. Демона управления и детей, подключенных к БД (DBI lib), дети собирают почту через imap (Mail::IMAPClient lib) тоже. 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 

для сна я использую usleep из Time::HiRes Lib. В remote_imap.pl usleep(100000), In remote_imapd.pl - usleep(500000).

Почему память не отпущена, потому что я сделал andef для всех переменных (кроме id_connet для DB)? Если хочешь, я добавлю код.

Главный демон remote_imap.pl Детского remote_imapd.pl

+2

добавить * минимальный * код, которого достаточно, чтобы воспроизвести проблему. –

+1

Yup нужно будет увидеть код, чтобы понять, где выделяется память. –

+0

Я добавляю гиперссылки – user3751471

ответ

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 петли и попытался 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; 

Из интереса - почему вы это делаете? Не могли бы вы охватить их внутри цикла while, и вам не нужно будет их повторно использовать? Я не знаю, что это обязательно ваша проблема, хотя это может быть легко в одной из библиотек, которые вы импортируете. Тот факт, что это происходит с более занятым ребенком, подразумевает, что каждый цикл что-то попадает в массив или объект, который сохраняется.

+0

Я не помню, где, но я прочитал, что лучше использовать глобальные переменные и делать все в любом цикле 'while', прежде чем использовать локальные переменные. Но результат тот же. Я могу добавить весь ваш код с Lib.pm, если это необходимо. – user3751471

Смежные вопросы