Doctrine ORM Memory issues

匿名 (未验证) 提交于 2019-12-03 01:34:02

问题:

The Problem:

While running a Daemon service that uses Doctrine from the Factory classes below there is a memory issue. When the Daemon Service starts it runs about 175MB. A day later it's about 250MB, one more day and it's at 400MB. I'm looking as to what is causing the increase in memory and how I could bring it down.

Things I've tried:

  • $em->clear(); // This kinda helps
  • $em->close(); // this causes issues
  • $em->getConnection()->getConfiguration()->setSQLLogger(null);

    --env=prod should take care of setSQLLogger(null), correct?

Is there anything I should be doing to help with memory issues using Doctrine 2.x and Symfony 2.1.x?

Created a factory to handle connections

===================== START EMFactory =====================

<?php  namespace NS\Bundle\EMBundle;  use Doctrine\ORM\EntityManager;  class EMFactory {     /**      * @var      */     private $container;      /**      * @param $container      */     public function __construct($container)     {         $this->container = $container;     }      /**      * @return EntityManager      */     public function getBlahEntityManager()     {         return $this->getContainer()->get('doctrine.orm.blah_manager_entity_manager');     }      /**      * @return EntityManager      */     public function getFooEntityManager()     {         return $this->getContainer()->get('doctrine.orm.foo_manager_entity_manager');     }      /**      * @return EntityManager      */     public function getBarEntityManager()     {         return $this->getContainer()->get('doctrine.orm.bar_manager_entity_manager');     }      /**      * @return mixed      */     public function getContainer()     {         return $this->container;     }      /**      * @param $container      * @return $this      */     public function setContainer($container)     {         $this->container = $container;         return $this;     }      public function closeEntityManager(EntityManager $em)     {         try {             $em->clear(); // This kinda helps             //$em->close(); // this causes issues             //$em->getConnection()->getConfiguration()->setSQLLogger(null); // --env=prod should take care of this         } catch (\Exception $e) {             // exception here         }     } } 

===================== END EMFactory =====================

I use an Abstract Class that constructs the EMFactory

===================== Start Abstract Class =====================

/**  * @param \Symfony\Component\DependencyInjection\Container $container  */ public function __construct(Container $container) {     $this->container = $container;     $this->entityManagerFactory = new EMFactory($container); } 

===================== END Abstract Class =====================

Here is an example of how I'm using the EM, The class extends the Abstract class above

===================== START Working Example #1 =====================

// calling like this looks to be working as expected  $fooEM = $this->getEntityManagerFactory()->getFooEntityManager();  $barResults = $fooEM->getRepository('NS\Bundle\EMBundle\Entity\Bar')->findOneBy(array('id' => 1));  if (!is_object($barResults)) {     throw new \Exception("Bar is a non object."); }  // some logic here ...  $this->getEntityManagerFactory()->closeEntityManager($fooEM); 

===================== END Working Example #1 =====================

Here is another example of how I'm using the EM, The class extends the Abstract class above

===================== START Working Example #2 =====================

// calling from functions like this  $fooEM = $this->getEntityManagerFactory()->getFooEntityManager();  $dql = 'SELECT b.*         FROM NS\Bundle\EMBundle\Entity\Bar b                     WHERE b.id = :id';  $query = $fooEM->createQuery($dql); $query->setParameter('id', 1);  $barResults = $query->getResult();  $this->getEntityManagerFactory()->closeEntityManager($fooEM);  return $barResults; 

===================== END Working Example #2 =====================

Here is another example of how I'm using the EM, The class extends the Abstract class above

===================== START Working Example #3 =====================

// calling from functions like this  $fooEM = $this->getEntityManagerFactory()->getFooEntityManager();  $barEntity = new Bar(); $barEntity->setId(1); $barEntity->setComment('this is foo-ie');  $fooEM->persist($barEntity); $fooEM->flush();  $this->getEntityManagerFactory()->closeEntityManager($fooEM);  unset($barEntity); 

===================== END Working Example #3 =====================

These are just some basic examples but it's just the queries that get more complex.

Does anything stand out that say, Optimize me?

回答1:

Your issue might come from your instanciations of your entity managers. If you have a specific set of them, you might rather use Symfony2 Dependency Injection instead of calling the container.

Each time you use your accessors, you'll instantiate a new Entity Manager, hence consume more memory (and as it's a daemon, you never truly release it). By using DI, you'll always have the same instance.

Your EMFFactory should then look like this:

<?php  namespace NS\Bundle\EMBundle;  use Doctrine\ORM\EntityManager;  class EMFactory {     /**      * @var      */     private $fooEm;     /**      * @var      */     private $barEm;     /**      * @var      */     private $blahEm;      /**      * @param $fooEm      * @param $barEm      * @param $blahEm      */     public function __construct($fooEm, $barEm, $blahEm)     {         $this->fooEm = $fooEm;         $this->barEm = $barEm;         $this->blahEm = $blahEm;     }      /**      * @return EntityManager      */     public function getBlahEntityManager()     {         return $this->blahEm;     }      /**      * @return EntityManager      */     public function getFooEntityManager()     {         return $this->fooEm;     }      /**      * @return EntityManager      */     public function getBarEntityManager()     {         return $this->barEm;     }      /**      * @return mixed      */     public function getContainer()     {         return $this->container;     }      /**      * @param $container      * @return $this      */     public function setContainer($container)     {         $this->container = $container;         return $this;     }      public function closeEntityManager(EntityManager $em)     {         try {             $em->clear(); // This kinda helps             //$em->close(); // this causes issues             //$em->getConnection()->getConfiguration()->setSQLLogger(null); // --env=prod should take care of this         } catch (\Exception $e) {             // exception here         }     } } 

Then, tweak your service definitions to give the various EMs to your config, and define your EMFactory as a service as well.



回答2:

This solved the connection issue we were having.

Needed to close just the connection

public function closeEntityManager(EntityManager $em) {     try {         $em->clear(); // This kinda helps         $em->getConnection()->close(); // this seems to work                 } catch (\Exception $e) {         // exception here     } } 


易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!