php - Doctrine ORM 内存问题

标签 php memory symfony doctrine-orm

问题:

在运行使用下面工厂类中的 Doctrine 的守护进程服务时,存在内存问题。当守护进程服务启动时,它运行大约 175MB。一天后它大约是 250MB,再过一天它就变成了 400MB。我正在寻找导致内存增加的原因以及如何降低内存。

我尝试过的事情:

  • $em->clear();//这有点帮助
  • $em->关闭();//这会导致问题
  • $em->getConnection()->getConfiguration()->setSQLLogger(null);

    --env=prod 应该处理 setSQLLogger(null),对吗?

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

创建了一个工厂来处理连接

===================== 启动 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
        }
    }
}

===================== 结束 EMFactory =====================

我使用构造 EMFactory 的抽象类

=====================启动抽象类=====================

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

=====================结束抽象类=====================

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

===================== 开始工作示例 #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);

===================== 结束工作示例 #1 =====================

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

===================== 开始工作示例 #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;

===================== 结束工作示例 #2 =====================

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

===================== 开始工作示例 #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);

===================== 结束工作示例 #3 =====================

这些只是一些基本示例,但只是查询变得更加复杂。

有什么突出的说,优化我吗?

最佳答案

您的问题可能来自实体管理器的实例化。如果你有一组特定的它们,你可能宁愿使用 Symfony2 依赖注入(inject)而不是调用容器。

每次使用访问器时,您都会实例化一个新的实体管理器,因此会消耗更多内存(并且由于它是守护进程,您永远不会真正释放它)。通过使用 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
        }
    }
}

然后,调整您的服务定义以将各种 EM 提供给您的配置,并将您的 EMFactory 定义为服务。

关于php - Doctrine ORM 内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15572384/

相关文章:

javascript - 第二个元素没有在第一个元素的第一次调试中同时出现

php - 如何构建具有一定数量随机奖品的 'Click-to-Win' 类型竞赛

javascript - 这是 JavaScript 内存泄漏吗?

Symfony2 |从响应/转发中隐藏/删除 header

php - Symfony 从 Controller 设置 block 内容

javascript - Bootstrap.min.js 的 src 不工作

java - 安卓资源 : How are bitmaps loaded from resources handled memory wise?

Android Espresso - java.lang.OutOfMemoryError : GC overhead limit exceeded

php - Composer更新正在尝试删除根软件包

php - 如何解决问题 "The VirtualMerchant ID was not supplied in the authorization request"