Doctrine Paginator填满内存

Doctrine Paginator填满内存

问题描述:

我在PHP 7.0.22上使用了Docfine Paginator的Symfony命令。该命令必须处理来自大型表格的数据,因此我以100个项目为单位进行处理。问题是,在几百个循环后,它会填充256M内存。作为对OOM措施(外的内存)我使用:Doctrine Paginator填满内存

  • $em->getConnection()->getConfiguration()->setSQLLogger(null); - 禁用SQL记录器,填充内存用于运行许多SQL脚本记录的查询命令
  • $em->clear(); - 分离从学说中的所有对象在每次循环

我已经把一些垃圾场与memory_get_usage()检查发生了什么事情,似乎是在命令在每次调用$paginator->getIterator()->getArrayCopy();增加了回收不干净尽可能多的结尾。

我甚至试图手动收集垃圾每个循环与gc_collect_cycles(),但仍然没有区别,命令开始使用18M和增加约每隔几百个项目〜2M。还试图手动取消设置结果和查询生成器...什么也没有。我删除了所有的数据处理,只保留了select查询和paginator,并得到了相同的行为。

任何人有任何想法我应该看看下一个?

注意:对于这类操作,256M应该足够了,所以请不要推荐提示增加允许内存的解决方案。

条纹下来​​方法看起来是这样的:由学说分页程序产生

protected function execute(InputInterface $input, OutputInterface $output) 
{ 

    // Remove SQL logger to avoid out of memory errors 
    $em = $this->getEntityManager(); // method defined in base class 
    $em->getConnection()->getConfiguration()->setSQLLogger(null); 


    $firstResult = 0; 


    // Get latest ID 
    $maxId = $this->getMaxIdInTable('AppBundle:MyEntity'); // method defined in base class 
    $this->getLogger()->info('Working for max media id: ' . $maxId); 

    do { 

     // Get data 
     $dbItemsQuery = $em->createQueryBuilder() 
      ->select('m') 
      ->from('AppBundle:MyEntity', 'm') 

      ->where('m.id <= :maxId') 
      ->setParameter('maxId', $maxId) 

      ->setFirstResult($firstResult) 
      ->setMaxResults(self::PAGE_SIZE) 
     ; 

     $paginator = new Paginator($dbItemsQuery); 

     $dbItems = $paginator->getIterator()->getArrayCopy(); 

     $totalCount = count($paginator); 
     $currentPageCount = count($dbItems); 

     // Clear Doctrine objects from memory 
     $em->clear(); 


     // Update first result 
     $firstResult += $currentPageCount; 
     $output->writeln($firstResult); 
    } 
    while ($currentPageCount == self::PAGE_SIZE); 


    // Finish message 
    $output->writeln("\n\n<info>Done running <comment>" . $this->getName() . "</comment></info>\n"); 
} 

内存泄漏。我用Doctrine prepared statements用原生查询替换它并修复它。

  • 如果要更换学说分页程序,你应该重建分页功能,加入了限制查询:

    ,你应该考虑其他的事情。

  • --no-debug标志或-env=prod或两者都可以运行命令。问题是这些命令默认在dev环境中运行。这使得一些在prod环境中未使用的数据收集器成为可能。查看更多关于这个主题的Symfony documentation - How to Use the Console

编辑:在我特定情况下我还使用了实现HTTP狂饮库捆绑eightpoints/guzzle-bundle(在我的命令,某些API调用)。这个捆绑包也泄漏了,显然是通过一些中间件。为了解决这个问题,我不得不独立实例化Guzzle客户端,而没有EightPoints包。