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

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

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


person taw    schedule 09.01.2009    source источник


Ответы (5)


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

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

Возможно, вы сможете реорганизовать свою программу, чтобы воспользоваться этим фактом, явно вызвав undef($old_object) и в правильном порядке, аналогично тому, как программисты на Си говорят 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 может быть хорошим первым местом, но вам понадобится perl, созданный для отладки.

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

person geocar    schedule 09.01.2009
comment
@geocar, это здорово! Единственный надежный метод решения неизбежной проблемы утечки памяти в сложных программах на Perl, который я знаю. - person Vipul Ved Prakash; 23.08.2011

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

person Jesse    schedule 09.01.2009

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

person Craig H    schedule 09.01.2009

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

person Yuval F    schedule 09.01.2009
comment
Не думаю, что это сработает. Perl - это интерпретируемый язык. Разве valgrind не будет просто указывать на вызовы выделения памяти в интерпретаторе Perl? - person Ferruccio; 09.01.2009
comment
Никакой valgrind не может работать с Perl, просто используйте правильные параметры. это задокументировано. он должен присоединиться к скомпилированному исполняемому файлу, а не к двоичному файлу perl. - person casey; 26.07.2010
comment
valgrind обнаружит утечки памяти в коде XS, но не в коде Perl. Используйте для этого Devel :: Cycle или Devel :: Leak. - person rjh; 15.02.2013

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

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

person Tim Bunce    schedule 20.07.2015