Каков наилучший метод очистки памяти в PHP? (5.2)

У меня два простых вопроса. Что лучше / полезно для очистки памяти.

$var = null;

or

unset($var);

У меня одна функция с одним циклом. Я получаю (через несколько минут)

Fatal error: Allowed memory size of 419430400 bytes exhausted

Я устанавливаю null и unset () для каждого объекта (в конце цикла), но все равно безуспешно :( Я не могу узнать, что потребляет память.

А как насчет циклических вызовов функций? Освободит ли PHP все выделения в этих функциях? (После вызова)


person Michal Drozd    schedule 05.08.2010    source источник
comment
Как выглядит ваш код, из-за которого возникает ошибка? Может одна из функций - интенсивная память. У меня это было например при работе с библиотекой gd.   -  person JochenJung    schedule 05.08.2010


Ответы (5)


Сам PHP иногда путает обе концепции, но в целом переменная, установленная в NULL, не то же самое, что переменная, которая не существует:

<?php

$foo = 'One';
$bar = 'Two';

$foo = NULL;
unset($bar);

var_dump($foo); // NULL
var_dump($bar); // Notice: Undefined variable: bar
var_dump(get_defined_vars()); // Only foo shows up: ["foo"]=> NULL

?>
person Álvaro González    schedule 05.08.2010
comment
Эта путаница в основном может быть отнесена к ложному предположению, что isset является эквивалентом unset. Unset удаляет символ переменной из текущей области, где as isset также проверяет, существует ли он И не null. Например, isset($foo) и isset($bar) оба вернут false в приведенном выше примере. - person Denis 'Alpheus' Cahuk; 05.08.2010
comment
Кроме того, я бы не стал помещать закрывающий разделитель ?> в блоки кода на SO. Излишне (немного) затрудняет чтение кода. - person Denis 'Alpheus' Cahuk; 05.08.2010
comment
Помимо этой путаницы, на самом деле очень трудно отличить NULL от unset. Серьезно: stackoverflow.com/questions/2283647/ - person Álvaro González; 05.08.2010

unset () делает именно это, он сбрасывает переменную; но при этом не происходит немедленного освобождения памяти.

Сборщик мусора PHP фактически освобождает память, ранее используемую переменными, которые теперь не установлены, но только во время его работы. Это может произойти раньше, когда циклы ЦП не используются активно для другой работы или до того, как скрипту в противном случае не хватит памяти ... в зависимости от того, что произойдет раньше.

И имейте в виду, что unset не обязательно освободит память, используемую переменной, если у вас есть другие ссылки на эту переменную. Он просто удалит ссылку и уменьшит счетчик ссылок для фактически сохраненных данных на 1.

РЕДАКТИРОВАТЬ. При отключении не происходит немедленного освобождения используемой памяти (на самом деле это делает только сборка мусора), память, которая больше не используется в результате, доступна для объявления новых переменных.

person Mark Baker    schedule 05.08.2010
comment
Спасибо, а когда выйдет? Я прикрепил свой фрагмент кода. Когда я запускаю его, через первые 5 минут я получаю фатальную ошибку, исчерпано 400 МБ .. - person Michal Drozd; 05.08.2010
comment
Это все неправильно. unset освобождает память в том же смысле, что и сборщик мусора (который, кстати, существует только с PHP 5.3), то есть они возвращают блоки распределителю памяти, если базовое хранилище переменной больше не имеет ссылок. - person Artefacto; 05.08.2010
comment
unset () делает память, используемую переменной, доступной для повторного использования (путем уменьшения значения zval refcount), но не освобождает ее. Движок Zend знает, что блок памяти доступен для повторного использования, когда zval refcount равен нулю. Сборка мусора фактически освобождает память, фактически вызывая вызов C free (). По крайней мере, я так понимаю. Хотя я признаю, что это понимание основано на множестве противоречивых источников. - person Mark Baker; 05.08.2010
comment
ты прав. Единственное изменение, которое они внесли в PHP 5.3, заключалось в том, что теперь сборщик мусора (предположительно) может обрабатывать циклические ссылки (что не работает в PHP 5.2 или ниже, поэтому у вас может скоро закончиться память, поскольку объекты никогда не освобождались, если бы у вас были циркулярные ссылки). - person wimvds; 05.08.2010

Я обнаружил проблему.

Сначала это было вызвано инструментами профилирования xdebug (я все включил :)) - и они потребляют много памяти.

Так что помните: xdebug (при включенном профилировании) потребляет некоторую память в процессе PHP вашего приложения.

Во-вторых, я не выпустил статические члены, используемые в вызываемых функциях.

person Michal Drozd    schedule 05.08.2010
comment
но это не ответ на ваш вопрос. ЧТО лучше с точки зрения памяти, отключено или установлено значение null - person Arnold Roa; 09.09.2014

Если вы отключите переменную, она будет просто помечена, поэтому при следующей сборке мусора она будет удалена. Если установлено значение null, данные переменной перезаписываются.

См. Также комментарии к руководству по php: Unset Manual

По крайней мере, с таким поведением я сталкивался до сих пор. Но чтобы это исправить, сначала нужно попытаться выяснить, что вызывает рост памяти. Для этого может оказаться полезной функция memory_get_usage.

person enricog    schedule 05.08.2010

And what about function calls in cycle? Will PHP release all allocations in these functions?(after call)

Как только выполнение выходит за пределы функции, все нестатические переменные удаляются из памяти.

person Mchl    schedule 05.08.2010
comment
Спасибо, но вопрос в том, когда? сразу после звонка? - person Michal Drozd; 05.08.2010
comment
Я спрашиваю вас, потому что знаю, что PHP глуп в этой области. Для других языков это само собой разумеющееся. - person Michal Drozd; 05.08.2010
comment
Как можно быстрее. Я не хочу говорить «немедленно», потому что это может быть не совсем так (особенно если мы имеем дело с ресурсами) - person Mchl; 05.08.2010