Perl: как освободить память, выделенную для скаляра, без доступа к переменной Perl?

этот вопрос связан с ответ к бывшему вопрос об обработке памяти по Perl. Я узнал, что можно освободить память в Perl, явно используя undef функция на доступном скаляре и использование Devel::Peek или Devel::Size или такой можно увидеть, сколько памяти выделяется для скаляра. Во всех этих случаях отлаженные скаляры используются в пределах их области.

но можно ли отлаживать такие вещи, как выделенная память за пределами область переменных, только на уровне интерпретатора Perl? Что-то вроде поиска всей выделенной памяти для всех "вещей", которые являются скаляром в текущем интерпретаторе и печатают связанные с ними данные, такие как текущее значение или такие?

и если это так, если у кого-то уже есть эта информация, можно ли даже освободить известную память? Так же, как позвонить undef на скаляре, но без скаляра, что-то более низкий уровень, как на этих" вещах " вывода Devel::Peek.

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

наконец, и, возможно, самый большой выигрыш-повторное использование памяти: поскольку вызовы выполняются в подпрограммы Perl, выделения памяти производятся для переменных, когда они используются впервые. Последующее использование переменных может выделить больше памяти, например, если скалярная переменная должна содержать более длинную строку, чем раньше, или в массив добавлены новые элементы. В качестве оптимизации Perl зависает на этих распределениях, хотя их значения "выходят за рамки".

https://perl.apache.org/docs/2.0/user/intro/overview.html#Threads_Support

я мог бы найти много пакетов мониторинга и отладки вокруг низкий уровень доступа к памяти, но пока нет подсказки, как можно назвать что-то вроде undef функция на некоторой низкоуровневой структуре Perl в Perl. Возможно, просто невозможно без каких-либо XS или таких...

3 ответов


можно ли отлаживать такие вещи, как выделенная память вне области переменных

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

но пока нет подсказки, как можно вызвать что-то вроде функции undef на какой-то низкоуровневой структуре Perl в язык Perl.

это потому, что нет таких структур.

так же, как вызов undef на скаляре, но без скаляра, что-то более низкое, как на тех "вещах", вывод Devel::Peek.

Devel:: единственная функция Peek,Dump выводит вещи на переменные. Как вы и сказали,undef Это то, что вы хотели бы очистить эти.


из него очевидно, вы хотите знать, как освободить память, связанную с переменными в абз.

вы также упустили из виду тот факт, что многие операторы имеют связанную переменную (называемую "target"), в которой они возвращают свой результат.

подход 1

простой способ очистить все эти переменные-выборочно очистить таблицу символов (%::). Это позволит эффективно "разгрузить" каждый модуль. Убедитесь, что не очищены основные компоненты (perl -E'say for sort keys %::'). И не забудь ясно!--5--> так модули можно перезагрузить.

если очистка таблицы символов является подходом, который вы хотите принять, это может быть менее рискованным и трудоемким, чтобы сделать снимок %:: на ранней стадии и восстановить этот снимок, когда пришло время очистить символ.

подход 2

если вы не хотите перезагружать модули, вы можете попытаться найти каждую подлодку и восстановить их vars, а затем восстановить vars их операций.

vars подводной лодки существует в его колодки. Удобно, так что цели операции. Есть площадка для каждого уровня рекурсии, который испытал суб.

учитывая ссылку на sub, вы можете найти переменные в колодках sub. Вы можете обратиться к PadWalker для примера того, как это сделать. Вы не можете использовать PadWalker, так как он возвращает только одну переменную на имя переменной, даже если их несколько (из-за того, что несколько переменных объявляются с одинаковыми имя, или из-за рекурсии).

захваченные переменные и our переменные следует оставить нетронутыми. Можно определить, является ли запись pad одним из них. (Опять же, обратитесь к PadWalker.)

(очевидно, вы также можете посмотреть на освобождение дополнительных колодок суб!)

как вы находите все Сабы? Ну, навигация по таблице символов даст вам большинство из них. Найти их будет сложнее.

подход 3

в наиболее эффективный подход-просто завершить поток/процесс mod_perl. Новый чистый будет автоматически порожден. Это также самое простое в реализации, так как это просто изменение конфигурации (настройка MaxRequestsPerChild to 1).


другая форма потерянной памяти-утечка памяти. Это еще один большой вопрос, так что я его не касаюсь.


Я думаю, что вы ищете ответ на подобный вопрос. Все, что вам действительно нужно знать, вы можете найти во внутренностях к Devel::MAT::* submodules. А именно:Devel::MAT:: самосвал.xs, который имеет структуру кучи для интерпретатора perl. Модуль предназначен для сброса кучи по сигналу и анализа ее позже, но я думаю, вы можете превратить ее в проверку времени выполнения. Если вам нужна помощь по чтению XS, посмотрите здесь.


для отладки выделения памяти вы должны перекомпилировать perl с -Accflags=-DPERL_MEM_LOG DOC

(см. смежный вопрос о как перекомпилировать perl)

возможно, Вам будет интересно ОТЛАДЧИКИ ПАМЯТИ

чтобы освободить скаляр perl, так же, как когда он покидает ее область:

{ # Scope enter
     my $x; # Memory allocation
} # << HERE $x is freed

вы должны просто уменьшить его переменной REFCNT времени SvREFCNT_dec макрос DOC

в освободите SV, который вы создали, вызовите SvREFCNT_dec (SV*) . Обычно этот вызов не требуется (см. справочные подсчеты и смертность).

вот псевдо код:

{ 
    $x;
    call_xs_sub( $x ); # << HERE $x is freed        
}

XS псевдо-код:

call_xs_sub( SV *sv ) {
    ...
    SvREFCNT_dec( sv ); # <<HERE scalar is freed
    ...
}

чтобы шпионить за каждым выделением памяти, вы должны ходить по аренам perl.

во время компиляции вы можете просматривать любое место, где переменная объявлена и доступна с помощью B:: Xref модуль

или запустите perl с -Dm option (perl должен быть скомпилирован с соответствующими параметрами. Смотрите это темы):

perl -Dm script.pl