Как я могу найти утечки памяти в долго работающей программе Perl? - PullRequest
37 голосов
/ 09 января 2009

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

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

Ответы [ 5 ]

36 голосов
/ 09 января 2009

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

Знание того, как malloc() выделяет память, важно для ответа на больший вопрос, и оно варьируется от системы к системе, но в целом большинство реализаций malloc() оптимизированы для программ, выделяющих и освобождающих их в виде стеков. Perl использует подсчет ссылок для отслеживания памяти, что означает, что освобождение памяти означает, что (в отличие от языка на основе 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 может быть хорошим первым местом, но для отладки вам понадобится Perl.

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

5 голосов
/ 10 января 2009

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

3 голосов
/ 09 января 2009

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

2 голосов
/ 20 июля 2015

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

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

2 голосов
/ 09 января 2009

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

...