Evitando vazamentos de memória no Symfony2 Doctrine EntityManager

Caso:

======
O script de migração usa muitas consultas do Doctrine. No caso de migração de dados de lote, pode ocorrer falha devido ao limite de memória atingido.

Problema:

====== O
script PHP está consumindo memória após cada consulta e modificação de dados. Isso significa vazamentos de memória se o processo PHP for longo. Quando o limite de memória é atingido, o script lança uma exceção e o processo de migração falha.

Solução:

======
Aqui estão algumas dicas de como controlar o uso de memória ao usar Symfony2 e Doctrine EntityManager. Você é capaz de manter o consumo de memória em um nível razoável.

  • Lembre-se de remover o objeto se não for necessário

unset($obj);

ou

$obj = null;

Ambos fazem o mesmo, mas unset () não força a liberação imediata de memória. O coletor de lixo do PHP fará isso quando achar necessário – intencionalmente logo, já que esses ciclos de CPU não são necessários de qualquer maneira ou tão tarde quanto antes de o script ficar sem memória, o que quer que ocorra primeiro. Usando $ obj = null; irá reescrever os dados da variável. Ele pode liberar memória mais rapidamente, mas pode roubar os ciclos da CPU do código que realmente precisa deles mais cedo, resultando em um tempo de execução geral mais longo, mas menor consumo de memória.

  • Defina nenhum registro e definição de perfil em config.yml
doctrine:
dbal
:
connections
:
conn1
:
driver
: ...
...
logging
: false
profiling
: false
  • Ajuste o php.ini para usar toda a memória disponível do servidor.

memory_limit = -1

Pode ser perigoso. Lembre-se de habilitá-lo apenas para o processo de migração. Depois disso, defina para algum valor realizável. Ele permite que você use uma grande quantidade de memória, se necessário, para evitar erros de falta de memória.

  • Se você estiver usando PHP pelo menos 5.3 você pode forçar a coleta de lixo após destruir o objeto

gc_collect_cycles();

* Lembre-se de ligar primeirogc_enable()

  • Use funções de limpeza do EntityManager
$this->em->detach($obj);
$this
->em->flush();
$this
->em->clear();
  • Desativar SQL Logger

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

O Doctrine por padrão registra todas as consultas. Desligá-lo salvará o consumo de memória extra.