【问题标题】:Program runs out of memory reading a large TYPO3 Extbase repository程序在读取大型 TYPO3 Extbase 存储库时内存不足
【发布时间】:2016-10-09 01:54:09
【问题描述】:

我正在 TYPO3 CMS 6.2 Extbase 中编写一个扩展函数,它必须处理大型存储库中的每个对象。如果我有大约 10,000 个对象,我的函数可以正常工作,但如果我有超过 20,000 个对象,则内存不足。如何处理更大的存储库?

$importRecordsCount = $this->importRecordRepository->countAll();
for ($id = 1; $id <= $importRecordsCount; $id++) {
    $importRecord = $this->importRecordRepository->findByUid($id);
    /* Do things to other models based on properties of $importRecord */
}

程序在通过上面的findByUid() 行后,在TYPO3\CMS\Core\Utility\GeneralUtility::instantiateClass( ) 中超出了..\GeneralUtility.php:4427 附近的内存。在我最近的测试中,出现此错误需要 117 秒。错误信息是:

致命错误:在 ... \typo3\sysext\core\Classes\Utility\GeneralUtility.php 第 4448 行中已用尽 134217728 字节的允许内存大小(尝试分配 4194304 字节)

如果重要的话,我不使用@lazy,因为我稍后会在函数中进行一些处理。

【问题讨论】:

    标签: typo3 extbase typo3-6.2.x


    【解决方案1】:

    Extbase 还有 clearState 函数来释放一些内存:

    $this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class)->clearState();
    

    【讨论】:

      【解决方案2】:

      根据TYPO3官方网站,建议256M内存限制而不是128M: Source

      所以我的第一个建议是先尝试这样做,它现在可能会解决您的问题。你也应该使用 importRecordRepository->findAll();而不是通过迭代 uid 来获取每条记录,因为有人可能已经删除了一些记录。

      【讨论】:

      • 在我的开发环境中将 php.ini memory_limit 从 128M 增加到 256M 解决了这个问题。
      【解决方案3】:

      一般来说,Extbase 并不真正适合处理如此大量的数据。如果需要正确的历史记录等,另一种方法是使用DataHandler。与使用 TYPO3 数据库 API (DatabaseConnection, $GLOBALS['TYPO3_DB']) 相比,它也有相当多的开销,这将是最佳性能方法。在this answer 中查看我的 cmets 和教程。

      如果您决定继续使用 Extbase API,唯一可行的方法是保留每个 X 项(尝试在您的设置中可行的方法)以释放一些内存。从您的代码中,我无法真正看到您的操作在哪一点起作用,但以此为例:

      $importRecords = $this->importRecordRepository->findAll();
      $i = 0;
      foreach ($importRecords as $importRecord) {
          /** @var \My\Package\Domain\Model\ImportRecord $importRecord */
          // Manipulate record
          $importRecord->setFoo('Test');
          $this->importRecordRepository->update($importRecord);
      
          if ($i % 100 === 0) {
              // Persist after each 100 items
              $this->persistenceManager->persistAll();
          }
      
          $i++;
      }
      // Persist the rest
      $this->persistenceManager->persistAll();
      

      【讨论】:

      • 我编辑了我的问题以显示我从 $importRecord 中的数据操作其他模型的点。
      • 我决定在这个案例中继续使用 Extbase API,并使用您的迭代持久性技术。这解决了问题,但只有当我还编辑 php.ini 以将 memory_limit 从 128M 增加到 256M 并将 max_execution_time 从 240 增加到 960 时。
      猜你喜欢
      • 1970-01-01
      • 2023-04-09
      • 1970-01-01
      • 2011-12-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多