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




3 Answers

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

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

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

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

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




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




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

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




Related