сборка мусора php во время работы скрипта - PullRequest
16 голосов
/ 24 июня 2010

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

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

Есть предложения?

Ответы [ 4 ]

16 голосов
/ 24 июня 2010

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

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

PHP сохраняет счетчик ссылок для всех переменных и уничтожает их (в большинстве случаев), как только этот счетчик ссылок становится равным нулю.Объекты имеют один внутренний счетчик ссылок, а сами переменные (ссылки на объекты) имеют один счетчик ссылок.Когда все ссылки на объекты были уничтожены из-за того, что их ссылочные блоки достигли 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.

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

3 голосов
/ 24 июня 2010

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

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

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

Вы по-прежнему будете видеть увеличение памяти во время выполнения, так как ГХ может свободно освобождать ее по собственному усмотрению, например, когда есть свободные циклы ЦП или когда у нее начинает заканчиваться память.

2 голосов
/ 24 июня 2010

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

1 голос
/ 24 июня 2010

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...