Использование профилей памяти Perl и обнаружение утечки?

Я написал постоянную сетевую услугу в Perl, которая работает в Linux.

К сожалению, по мере того, как он запускается, его размер стека (RSS) просто растет, растет и медленно, но уверенно растет.

Это несмотря на прилежные усилия с моей стороны, чтобы исключить все ненужные ключи hashа и удалить все ссылки на объекты, которые в противном случае заставили бы подсчет ссылок оставаться на месте и препятствовали сбору мусора.

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

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

    У вас может быть круговая ссылка в одном из ваших объектов. Когда сборщик мусора приходит, чтобы освободить этот объект, круговая ссылка означает, что все, о чем говорится в этой ссылке, никогда не будет освобождено. Вы можете проверить циклические ссылки с помощью Devel :: Cycle и Test :: Memory :: Cycle . Одна вещь, которую нужно попробовать (хотя она может стать дорогой в производственном коде, поэтому я бы отключил ее, когда флаг отладки не установлен) проверяет циклические ссылки внутри деструктора для всех ваших объектов:

    # make this be the parent class for all objects you want to check; # or alternatively, stuff this into the UNIVERSAL class's destructor package My::Parent; use strict; use warnings; use Devel::Cycle; # exports find_cycle() by default sub DESTROY { my $this = shift; # callback will be called for every cycle found find_cycle($this, sub { my $path = shift; foreach (@$path) { my ($type,$index,$ref,$value) = @$_; print STDERR "Circular reference found while destroying object of type " . ref($this) . "! reftype: $type\n"; # print other diagnostics if needed; see docs for find_cycle() } }); # perhaps add code to weaken any circular references found, # so that destructor can Do The Right Thing } 

    Вы можете использовать Devel :: Leak для поиска утечек памяти. Тем не менее, документация довольно редкая … например, где же получить ссылку $ handle для перехода на Devel::Leak::NoteSV() ? Я найду ответ, я отредактирую этот ответ.

    Хорошо, получается, что использование этого модуля довольно просто (код, украденный без стыда с Apache :: Leak ):

     use Devel::Leak; my $handle; # apparently this doesn't need to be anything at all my $leaveCount = 0; my $enterCount = Devel::Leak::NoteSV($handle); print STDERR "ENTER: $enterCount SVs\n"; # ... code that may leak $leaveCount = Devel::Leak::CheckSV($handle); print STDERR "\nLEAVE: $leaveCount SVs\n"; 

    Я бы поставил как можно больше кода в средней части, при этом проверка leaveCount как можно ближе к концу выполнения (если таковая имеется) – после того, как большинство переменных были освобождены как можно скорее (если вы не можете получить переменная, выходящая за пределы области видимости, вы можете присвоить ей undef, чтобы освободить все, что она указывала).

    Что еще нужно попробовать (не уверен, что это будет лучше всего помещено в комментарии после вышеописанного вопроса Алекса): что бы я попробовал дальше (кроме Devel :: Leak):

    Попытайтесь устранить «ненужные» части вашей программы или сегментируйте ее в отдельные исполняемые файлы (они могут использовать сигналы для связи или, возможно, друг с другом с аргументами командной строки) – цель состоит в том, чтобы свести исполняемый файл в наименьшую сумму кода, который по-прежнему демонстрирует плохое поведение . Если вы уверены, что это не ваш код, который делает это, уменьшите количество внешних модhive, которые вы используете, особенно те, которые имеют реализацию XS. Если, возможно, это ваш собственный код, найдите что-нибудь потенциально подозрительное:

    • определенно любое использование кода Inline :: C или XS
    • прямое использование ссылок, например \@list или \%hash , а не предопределенные ссылки, такие как [qw (foo bar)] (первая создает другую ссылку, которая может быть потеряна, а в последнем есть только одна ссылка, о которой нужно беспокоиться, который обычно хранится в локальном лексическом скаляре
    • манипулируя переменными косвенно, например $$foo где $foo изменен, что может вызвать автоматическую передачу переменных (хотя вам нужно отключить strict 'refs' проверку strict 'refs' )

    Хороший справочник об этом включен в руководство Perl: отладка использования памяти Perl

    Недавно я использовал NYTProf как профилировщик для большого приложения Perl. Он не отслеживает использование памяти, но отслеживает все выполняемые коды кода, которые помогают выяснить, откуда возникают утечки. Если то, что вы протекаете, – это ограниченные ресурсы, такие как соединения с базой данных, отслеживание там, где они выделены и закрыты, – это долгий путь к поиску утечек.

    Interesting Posts

    Какова цель этого 4-контактного кабеля с 3 проводами, которые поставляются со старым DVD-приводом IDE?

    ERROR ITMS – 90167 № пакета приложений, найденные в пакете

    Перенос выбранных приложений из резервной копии Time Machine

    Как настроить Firefox абсолютно не удалять элементы истории?

    Разница между Windows и консольным приложением

    Преобразование столбца в pandas dataframe из int в строку

    С скриптом оболочки, можно сказать, когда он запускается с помощью cron vs run вручную?

    Ubuntu 10 на виртуальном поле в качестве сервера для хоста Windows 7

    Как очистить все хранилище HTML5 от Safari?

    Эквивалент typedef в C #

    Поверните изображение MATLAB в изображение

    Как обновить новую версию eclipse вместо использования нового загруженного пакета

    Невозможно показать 64-битный вариант в VB Windows 10

    Отсутствие разрешения на открытие папки пользователя

    Передайте модель controllerу с помощью JQuery / Ajax

    Давайте будем гением компьютера.