我正在遇到在具有较低内存限制的Symfony项目上工作的问题。我需要创建多个实体,将它们添加到另一个实体(实体是关联的(,然后将其刷新到数据库中。这发生在while
循环中。
问题在于,有时循环无法完成整个周期,因为该过程崩溃了记忆耗尽。当然我无法提高内存限制。
我尝试通过一些代码更好地解释您...
实体结构
class Device
{
/**
* @ORMManyToMany(targetEntity="Resource", inversedBy="devices",cascade={"persist", "refresh"}, fetch="EXTRA_LAZY")
*/
protected $resources;
public function addResource(Resource $resource)
{
if ($this->resources->contains($resource)) return;
$this->resources->add($resource);
$resource->addDevice($this);
}
}
class Resource
{
/**
* @ORMManyToMany(targetEntity="Device", mappedBy="resources")
*/
protected $devices;
public function addDevice(Device $device)
{
if ($this->devices->contains($device)) return;
$this->devices->add($device);
$device->addResource($this);
}
}
循环
function doIt(Device $device) {
while(...) {
$res = new Resource(...);
$device->addResource($res); // store $res in memory until end
}
$em->persist($device);
$em->flush();
}
因此,问题是在循环完成之前,$device
保持内存Resource
对象,有时达到内存限制。
我到目前为止尝试的
function doIt(Device $device) {
$i = 0;
while(...) {
$res = new Resource(...);
$device->addResource($res);
$i++;
if ($i % 100 == 0) {
$em->persist($device);
$em->flush($device);
$device->setResources(null); // free up Resources in memory
$em->refresh($device); // Resources are not stored in memory
}
}
$em->persist($device);
$em->flush();
}
这也不是很好,因为我无论如何都会看到记忆的提升(可能是由学说引起的(。此外
您会做什么?
您可以尝试改善情况:
禁用导入的设置阶段中的理论SQL记录机构
$this->getContainer()->get('doctrine')->getConnection()->getConfiguration()->setSQLLogger(null);
尝试定期调用一个清晰的调用(我在处理并冲洗一批项目后要做(,但以前阅读文档,因为可能会根据您的代码有副作用
$this->entityManager->clear();
您似乎已经清除了所有未使用的对象和变量,您也可以尝试在php
中调用手册gc_collect_cyclegc_collect_cycles();
如果您使用Symfony命令执行导入,请确保使用--no-debug
flag
尽管没有达到完整的内存中立性,但在我的项目中与导入命令的工作正常,但其余的泄漏可以忽略不计。也许这在您的情况下可能会有所帮助。
我永远不会在冲洗后坚持50个实体。尝试将$ i降低到50或更少。也许有帮助。