考虑以下代码(包装在函数中):
$manager = $this->manager; // local ref
$q = $manager->createQuery('select c from VendorFeedBundle:Category c');
$iterableResult = $q->iterate();
$i = 0;
$batchSize = 500;
foreach($iterableResult as $row) {
$category = $row[0];
$struct = explode(' ' . $this->separator . ' ', $category->getPath());
unset($struct[count($struct) - 1]);
$path = implode(' ' . $this->separator . ' ', $struct);
if (!$parent = $this->repo->findOneBy(['path' => $path])) {
continue;
}
$category->setParent($parent);
// flush every x entities
if (($i % $batchSize) == 0) {
echo 'Flushing batch...' . "n";
echo 'Memory: ' . $this->getReadableSize(memory_get_usage()) . "n";
$manager->flush();
$manager->clear();
echo 'After batch...' . "n";
echo 'Memory: ' . $this->getReadableSize(memory_get_usage()) . "n";
}
++$i;
}
// flush the remaining
$manager->flush();
$manager->clear();
它在我的终端中记录以下内容:
Creating tree...
Memory: 14.91 MB
Flushing batch...
Memory: 18.46 MB
After batch...
Memory: 18.79 MB
Flushing batch...
Memory: 21.01 MB
After batch...
Memory: 23.29 MB
Flushing batch...
Memory: 25.36 MB
After batch...
Memory: 27.87 MB
Flushing batch...
Memory: 29.88 MB
.... etc
getReadAbleSize 方法不会将任何变量泄漏到全局范围或任何内容。我已经阅读并遵循了有关 doctrine2 批量插入/更新(批处理)的建议:http://docs.doctrine-project.org/en/latest/reference/batch-processing.html
我做错了什么?每 3 个项目增加 500 MB 内存对我来说似乎是一个(小)泄漏。
旁注:我需要以这种方式更新项目,因为我的系统分为 2 个进程;首先我插入类别,其次我更新父关系。
我的类别类是一个基本的 Doctrin2 实体,其中添加了一些 Gedmo 扩展(树、可翻译、可时间戳)请参阅:http://pastie.org/private/oiiyf54zjuouhiqjsjislg
我的完整脚本(正在迭代和更新类别):http://pastie.org/private/k5x240vr4taepczhqa4tva
- 将 SQL 记录器设置为空
$em->getConnection()->getConfiguration()->setSQLLogger(null);
$em->clear()
后手动调用函数gc_collect_cycles()
$em->clear();
gc_collect_cycles();
不要忘记将zend.enable_gc设置为 1,或者在使用 gc_collect_cycles() 之前手动调用 gc_enable()
- 如果从控制台运行命令,请添加
--no-debug
选项。