Подтвердить что ты не робот

Как я могу найти утечки памяти в долгосрочной программе Perl?

Perl использует подсчет ссылок для GC, и довольно легко сделать круговую ссылку случайно. Я вижу, что моя программа, похоже, использует все больше и больше памяти, и она, вероятно, переполнится через несколько дней.

Есть ли способ отладить утечки памяти в Perl? Хорошим началом было бы присоединение к программе и получение количества объектов разных типов. Если бы я знал, какие объекты намного больше, чем ожидалось, я мог бы проверить все ссылки на них и, надеюсь, исправить утечку.

4b9b3361

Ответ 1

Может быть, что Perl никогда не возвращает память в систему сама по себе: все до malloc() и всех правил, связанных с этим.

Знание того, как malloc() выделяет память, важно ответить на более важный вопрос и варьироваться от системы к системе, но в целом большинство реализаций malloc() оптимизированы для программ, распределяющих и освобождающихся от стека в виде заказов. Perl использует подсчет ссылок для отслеживания памяти, что означает, что deallocations, что означает (в отличие от языка, основанного на GC, который использует malloc() под ним), на самом деле не так сложно сказать, где будет происходить перераспределение, и в каком порядке.

Возможно, вы можете реорганизовать свою программу, чтобы воспользоваться этим фактом, - явно указав undef($old_object) - и в правильном порядке, подобно тому, как говорят C-программисты free(old_object);

Для длительных программ (дни, месяцы и т.д.), где у меня есть нагрузки циклов загрузки/копирования/дампа, я собираю мусор с помощью exit() and exec(), а там, где это невозможно, я просто собираю свои структуры данных (используя Storable) и дескрипторы файлов (с использованием $^F) и exec($0) - обычно с переменной окружения, установленной как $ENV{EXEC_GC_MODE}, и вам может понадобиться нечто подобное, даже если у вас нет каких-либо утечек потому что Perl пропускает небольшие куски, чтобы ваша система malloc() не могла понять, как вернуть.

Конечно, если у вас есть утечки в вашем коде, то остальная часть моего совета несколько более актуальна. Первоначально он был отправлен на другой вопрос по этому вопросу, но он явно не охватывал давно запущенные программы.


Все утечки памяти программы perl будут либо содержать XS на ссылке, либо круговую структуру данных. Devel:: Cycle - отличный инструмент для поиска циркулярных ссылок, если вы знаете, какие структуры могут содержать циклы. Devel:: Peek можно использовать для поиска объектов с более высоким, чем ожидалось, количеством ссылок.

Если вы не знаете, где еще искать, Devel:: LeakTrace:: Fast может быть хорошим первым местом, но вы 'll нужен perl, построенный для отладки.

Если вы подозреваете, что утечка находится внутри XS-пространства, это намного сложнее, и Valgrind, вероятно, будет вашим лучшим выбором. Test:: Valgrind может помочь вам снизить количество кода, необходимого для поиска, но это не будет работать в Windows, так что вы для этого нужно портировать (по крайней мере, протекающую часть) в Linux.

Ответ 2

Devel::Gladiator - еще один полезный инструмент в этом пространстве.

Ответ 3

Похоже, что модуль cpan Devel:: Cycle - это то, что вы ищете. Он требует внесения некоторых изменений в ваш код, но он должен помочь вам найти ваши ссылки без особых проблем.

Ответ 4

valgrind - отличное приложение для Linux, которое обнаруживает утечки памяти в запущенном коде. Если ваш код Perl работает в Linux, вы должны проверить его.

Ответ 5

В дополнение к другим комментариям вы можете найти полезную Perl Memory Use talk в LPW2013. Я рекомендую смотреть скринкаст, поскольку он объясняет слайды и имеет некоторые симпатичные визуальные эффекты и некоторые Q & A в конце.

Я также предлагаю рассмотреть модуль Paul Evans Devel::MAT, который я упоминаю в разговоре.