Сборка мусора php при запуске script

У меня есть PHP script, который работает на cron, который может занять до 15 минут. Через равные промежутки времени я выплевываю memory_get_usage(), чтобы я мог видеть, что происходит. В первый раз, когда он говорит мне, что я использую, я нахожусь в 10 мегабайтах. Когда заканчивается script, я нахожусь в 114 мегабайтах!

Выполняет ли PHP сборку мусора при запуске script? Или что происходит со всей этой памятью? Есть ли что-то, что я могу сделать, чтобы заставить сбор мусора. Задача, которую выполняет мой script, - это ночной импорт нескольких тысяч узлов в Drupal. Поэтому он делает то же самое много раз.

Любые предложения?

Ответ 1

Ключ в том, что вы unset свои глобальные переменные, как только они вам не нужны.

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

PHP хранит счетчик ссылок для всех переменных и уничтожает их (в большинстве условий), как только этот счетчик ссылок будет равен нулю. Объекты имеют один внутренний счетчик ссылок, а сами переменные (ссылки на объекты) имеют один счетчик ссылок. Когда все ссылки на объекты были уничтожены, потому что их ссылочные coutns достигли 0, сам объект будет уничтожен. Пример:

$a = new stdclass; //$a zval refcount 1, object refcount 1
$b = $a;           //$a/$b zval refcount 2, object refcount 1
//this forces the zval separation because $b isn't part of the reference set:
$c = &$a;          //$a/$c zval refcount 2 (isref), $b 1, object refcount 2
unset($c);         //$a zval refcount 1, $b 1, object refcount 2
unset($a);         //$b refcount 1, object refcount 1
unset($b);         //everything is destroyed

Но рассмотрим следующий сценарий:

class A {
    public $b;
}
class B {
    public $a;
}

$a = new A;
$b = new B;
$a->b = $b;
$b->a = $a;
unset($a); //cannot destroy object $a because $b still references it
unset($b); //cannot destroy object $b because $a still references it

Эти циклические ссылки включают в себя сборщик мусора PHP 5.3. Вы можете явно вызвать сборщик мусора с gc_collect_cycles.

См. также Основы подсчета ссылок и Циклы сбора данных в руководство.

Ответ 2

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

Используйте unset() для освобождения переменных, которые вы больше не используете. Если вы просто перезаписываете переменные (например, с нулевым значением), это позволит GC уменьшить до объема пространства, необходимого этой переменной, но не так сильно, как unset, что фактически позволяет уничтожить ссылочное значение.

Вы также должны правильно выпускать любые ресурсы и т.д., которые вы используете.

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

Ответ 3

Используйте unset() как можно больше, чаще проверяйте используемую память. да, php делает сборку мусора во время выполнения на нескольких условиях. здесь полезно post на php.net.

Ответ 4

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

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