2017-09-25 39 views
1

我在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"); 
} 

回答

0

內存泄漏。我用Doctrine prepared statements用原生查詢替換它並修復它。

  • 如果要更換學說分頁程序,你應該重建分頁功能,加入了限制查詢:

    ,你應該考慮其他的事情。

  • --no-debug標誌或-env=prod或兩者都可以運行命令。問題是這些命令默認在dev環境中運行。這使得一些在prod環境中未使用的數據收集器成爲可能。查看更多關於這個主題的Symfony documentation - How to Use the Console

編輯:在我特定情況下我還使用了實現HTTP狂飲庫捆綁eightpoints/guzzle-bundle(在我的命令,某些API調用)。這個捆綁包也泄漏了,顯然是通過一些中間件。爲了解決這個問題,我不得不獨立實例化Guzzle客戶端,而沒有EightPoints包。