程序耗尽内存读取大型TYPO3 Extbase存储库

时间:2016-06-08 16:55:42

标签: typo3 extbase typo3-6.2.x

我正在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 */
}

在通过上面的..\GeneralUtility.php:4427行后,该程序超出TYPO3\CMS\Core\Utility\GeneralUtility::instantiateClass( ) findByUid()附近的内存。在我的最新测试期间,花了117秒才达到此错误。错误消息是:

  

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

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

3 个答案:

答案 0 :(得分:1)

通常,Extbase不适合处理如此大量的数据。如果需要正确的历史记录等,则可以使用DataHandler。与使用TYPO3数据库API(DatabaseConnection$GLOBALS['TYPO3_DB'])相比,它也有相当大的开销,这将是性能最佳的方法。请参阅this answer中的评论和教程。

如果您决定使用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();

答案 1 :(得分:1)

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

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

答案 2 :(得分:0)

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

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