内存泄漏Symfony2 Doctrine2 /超出内存限制

Mon*_*roM 45 orm memory-leaks symfony doctrine-orm

实际上我对symfony2和doctrine2的组合有很多麻烦.我必须处理大量数据集(大约2-3百万次写入和读取),并且必须做很多额外的工作以避免内存不足.

我找出了2个要点,即"泄漏"内存(它们实际上并没有泄漏,而是分配了很多)

  1. Entitymanager实体存储(我不知道这个的真实名称)似乎它保留了所有处理过的entites,你必须定期清除这个存储

    $entityManager->clear()
  2. Doctrine QueryCache - 它缓存所有使用的查询,我发现的唯一配置是你能够决定你想要使用什么类型的Cache.我没有发现全局禁用每个查询禁用它的有用标志.因此通常使用该函数为每个查询对象禁用它

    $qb = $repository->createQueryBuilder($a);
    $query = $qb->getQuery();
    $query->useQueryCache(false);
    $query->execute();
    

所以..这就是我现在想出来的..我的问题是:

是否有一种简单的方法可以从Entitymanagerstorage中拒绝某些对象?有没有办法在entitymanager中设置querycache?我可以在symonfony doctrine配置中配置这种缓存行为吗?

如果有人对我有一些不错的提示,那将是非常酷的..否则这可能会帮助一些菜鸟......

CYA

Ser*_*rgi 86

有点晚了,但我想我刚刚 Benjamin Eberlei的Google网上找到了一个回复你问题的帖子:正如Doctrine Configuration Reference所述,默认情况下SQL连接的记录设置为kernel.debug的值,所以如果已将debug调试为true的实例化AppKernel,则SQL命令将在每次迭代时存储在内存中.

您应该将AppKernel实例化为false,在配置YML 中将日志记录设置为false,或者在使用EntityManager之前将SQLLogger手动设置为null

$em->getConnection()->getConfiguration()->setSQLLogger(null);
Run Code Online (Sandbox Code Playgroud)

  • 好样的!几个月来我们一直在努力解决这个问题! (4认同)
  • 这非常有帮助.我有一个我写的控制台命令(就像一个"守护进程"类型命令),它继续耗尽内存并且在对象管理器上使用`clear()`方法是不够的.禁用此SQL记录器可以解决这个问题.但是,由于我在控制台命令中,我不得不使用`$ this-> getContainer() - > get('doctrine') - > getEntityManager()`来实际到达实体管理器来执行此操作. (4认同)
  • 这是SF2的事情.你**真的需要阅读文档和代码来了解它是如何工作的.前几天我们发现我们没有在请求之间缓存DQL和元数据.我们这样做了[结束](https://coderwall.com/p/ry1y0a)请求的速度是更改前的两倍 (3认同)

Arn*_*anc 18

尝试使用--no-debug运行命令.在调试模式下,探查器会保留有关内存中每个查询的信息.


luc*_*nov 13

1.关闭日志记录和分析app/config/config.yml

doctrine:
    dbal:
        driver: ...
        ...
        logging: false
        profiling: false
Run Code Online (Sandbox Code Playgroud)

或者在代码中

$this->em->getConnection()->getConfiguration()->setSQLLogger(null);
Run Code Online (Sandbox Code Playgroud)

2.强制垃圾收集器.如果您主动使用CPU,那么垃圾收集器会等待,您很快就会发现自己没有内存.

首先启用手动垃圾收集管理.gc_enable()在代码中的任何位置运行.然后运行gc_collect_cycles()强制垃圾收集器.

public function execute(InputInterface $input, OutputInterface $output)
{
    gc_enable();

    // I'm initing $this->em in __construct using DependencyInjection
    $customers = $this->em->getRepository('AppBundle:Customer')->findAll();

    $counter = 0;
    foreach ($customers as $customer) {
        // process customer - some logic here, $this->em->persist and so on

        if (++$counter % 100 == 0) {
            $this->em->flush(); // save unsaved changes
            $this->em->clear(); // clear doctrine managed entities
            gc_collect_cycles(); // PHP garbage collect

            // Note that $this->em->clear() detaches all managed entities,
            // may be you need some; reinit them here
        }
    }

    // don't forget to flush in the end
    $this->em->flush();
    $this->em->clear();
    gc_collect_cycles();
}
Run Code Online (Sandbox Code Playgroud)

如果你的桌子非常大,请不要使用findAll.使用迭代器 - http://doctrine-orm.readthedocs.org/projects/doctrine-orm/en/latest/reference/batch-processing.html#iterating-results


Ser*_*nov 9

  1. 将SQL logger设置为null

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

  1. 手动调用函数gc_collect_cycles()$em->clear()

$em->clear(); gc_collect_cycles();

不要忘记将zend.enable_gc设置为1,或者在使用gc_collect_cycles()之前手动调用gc_enable ()

  1. --no-debug如果从控制台运行命令,请添加选项.


归档时间:

查看次数:

24436 次

最近记录:

9 年,9 月 前