2013-03-22 107 views
3

问题:Doctrine ORM内存问题

运行下面的Factory类中使用Doctrine的守护进程服务时,存在内存问题。当守护程序服务启动时,它运行大约175MB。一天之后,它大概是250MB,多一天,而且是400MB。我正在寻找什么导致了内存的增加以及我如何降低内存。

事情我已经尝试:

  • $ EM->明确(); // This kinda helps
  • $ em-> close(); //这导致问题
  • $ em-> getConnection() - > getConfiguration() - > setSQLLogger(null);

    --env = prod应该照顾setSQLLogger(null),对吗?

有什么我应该做的,以帮助解决使用Doctrine 2.x和Symfony 2.1.x的内存问题?

创建一个工厂来处理连接

===================== 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 ============ =========

我用一个抽象类,构建EMFactory

=====================开始抽象类=====================

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

===================== END抽象类=================== ==

下面是我如何使用EM为例,该类扩展上述

抽象类==================== = START工作实施例#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工作示例#1 =====================

这是另一个我如何使用EM的例子,该类扩展了上面的抽象类

===================== START工作示例#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工作实例#2 =====================

下面是我如何使用EM另一个例子,该类扩展摘要类以上

===================== START日夜不停g实施例#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工作实例#3 =====================

这些只是一些基本的例子,但它只是变得越来越复杂查询。

做任何事情脱颖而出的是说,我的优化?

+0

莫非任何所谓的“工作实例#2”保持的结果无限期? – 2013-03-22 14:22:20

+0

$ barResults?这在函数中是本地的,应该用每次新的调用覆盖。我是否应该清除它? @BeauSimensen – 2013-03-22 14:25:19

+0

'$ results = some_function(); // some_function是返回$ barResults'的代码是否有可能得到结果的代码不会以某种方式释放它们?没有别的东西真的跳出来对我。 – 2013-03-22 14:55:20

回答

0

这解决了我们遇到的连接问题。

需要关闭恰在连接

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

您的问题可能来自于你对你的实体管理instanciations。如果你有一套特定的集合,你可以使用Symfony2依赖注入而不是调用容器。

你每次使用存取时间,你会实例化一个新的实体管理器,因此消耗更多的内存(并因为它是一个守护进程,你从来没有真正释放)。通过使用DI,您将始终拥有相同的实例。然后

你EMFFactory应该是这样的:

<?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 
     } 
    } 
} 

然后,调整你的服务定义给各个新兴市场,以你的配置,并定义EMFactory作为服务也是如此。

+0

我从容器中获取的原因是我希望它在当前EM出现问题时拉出新的EM,否则现有连接将被重用。 – 2013-03-22 18:44:24

+0

您会遇到什么样的问题与当前EM?避免高内存使用的另一种方法是仍然使用容器,但将EM放入类变量(有点像单例设计模式)。如果您想强制重新启动,则可以释放当前EM使用的内存,然后重新创建一个新内存。但我仍然会用DI机制,这似乎更适合我。 – 2013-03-23 11:23:06