Как избежать утечек памяти EntityManager из Doctrine в Symfony2

  • 2,287
  • 0
  • 0
  • 0
  • 1 год назад

Ситуация

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

Проблема

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

Решение

Приведу несколько способов контролирования памяти при работе с EntityManager, которые позволят не допустить превышения лимита памяти.

Всегда удаляйте объект, если он вам больше не нужен

unset($obj); или $obj = null;

Оба способа по сути делают одно и то же, за одним исключением, unset() не освобождает память сразу же. Это делает сборщик мусора PHP или как только существуют доступное процессорное время, или когда как только скрипт подойдет к лимиту по памяти. При использовании $obj = null; данные переменной переписываются сразу же. Конечно память освобождается быстрее, но вы теряете процессорное время. В итоге скрипт может исполняться немного дольше, но потребление памяти будет ниже.

Отключите логирование и профилирование в config.yml
doctrine:
  dbal:
    connections:
      conn1:
        driver: ...
          ...
          logging: false
          profiling: false

Разрешите использование всей доступной памяти в php.ini

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

При работе с PHP версии 5.3 и выше вы можете запускать сборщик мусора после каждого уничтожения объекта gc_collect_cycles();. Не забудьте сначала вызвать gc_enable().

Применяйте функции очистки EntityManager()

$this->em->detach($obj);
$this->em->flush();
$this->em->clear();

Выключите SQL логирование

$this->em->getConnection()->getConfiguration()->setSQLLogger(null);

По-умолчанию Doctrine сохраняет все запросы. Отключив этот функционал вы значительно экономите на памяти.

Комментарии

0