程序在读取大型 TYPO3 Extbase 存储库时内存不足
Program runs out of memory reading a large TYPO3 Extbase repository
我正在 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 秒才出现这个错误。错误信息是:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4194304 bytes) in ... \typo3\sysext\core\Classes\Utility\GeneralUtility.php on line 4448
如果重要的话,我不会使用@lazy,因为我稍后会在函数中进行一些处理。
总的来说,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();
根据TYPO3官方网站,建议内存限制为256M而不是128M:
Source
所以我的第一个建议是先尝试这样做,它现在可能会解决您的问题。你也应该使用 importRecordRepository->findAll();而不是通过迭代 uid 来获取每条记录,因为有人可能删除了一些记录。
还有Extbase的clearState函数来释放一些内存:
$this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class)->clearState();
我正在 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 秒才出现这个错误。错误信息是:
Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4194304 bytes) in ... \typo3\sysext\core\Classes\Utility\GeneralUtility.php on line 4448
如果重要的话,我不会使用@lazy,因为我稍后会在函数中进行一些处理。
总的来说,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();
根据TYPO3官方网站,建议内存限制为256M而不是128M: Source
所以我的第一个建议是先尝试这样做,它现在可能会解决您的问题。你也应该使用 importRecordRepository->findAll();而不是通过迭代 uid 来获取每条记录,因为有人可能删除了一些记录。
还有Extbase的clearState函数来释放一些内存:
$this->objectManager->get(\TYPO3\CMS\Extbase\Persistence\Generic\PersistenceManager::class)->clearState();