DrK*_*Key 3 php memory memory-management symfony doctrine-orm
我在处理内存限制较低的 Symfony 项目时遇到问题。我需要创建多个实体,将它们添加到另一个实体(实体是关联的),然后将更改刷新到数据库。这是while循环发生的。
问题是有时循环无法完成整个循环,因为进程因内存耗尽而崩溃。当然我不能提高内存限制。
我尝试用一些代码更好地解释你......
class Device
{
/**
* @ORM\ManyToMany(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
{
/**
* @ORM\ManyToMany(targetEntity="Device", mappedBy="resources")
*/
protected $devices;
public function addDevice(Device $device)
{
if ($this->devices->contains($device)) return;
$this->devices->add($device);
$device->addResource($this);
}
}
Run Code Online (Sandbox Code Playgroud)
function doIt(Device $device) {
while(...) {
$res = new Resource(...);
$device->addResource($res); // store $res in memory until end
}
$em->persist($device);
$em->flush();
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,在循环结束之前,$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();
}
Run Code Online (Sandbox Code Playgroud)
即使我看到内存在提升(可能是由教义引起的),这效果也不是很好。此外,有很多实体以及它们之间的多个关联,检查数据库中的结果会给我一些错误(例如,实体未持久化)。
你会怎么办?
您可以尝试以下几项措施来改善这种情况:
在导入的设置阶段禁用 SQL 日志记录机制
$this->getContainer()->get('doctrine')->getConnection()->getConfiguration()->setSQLLogger(null);
Run Code Online (Sandbox Code Playgroud)
尝试定期调用clear(我在处理并刷新一批项目后执行此操作),但请先阅读文档,因为根据您的代码,可能会产生副作用
$this->entityManager->clear();
Run Code Online (Sandbox Code Playgroud)
您似乎已经清除了所有未使用的对象和变量,您也可以尝试在 php 中调用手动 gc_collect_cycle
gc_collect_cycles();
Run Code Online (Sandbox Code Playgroud)
如果您的导入是使用 symfony 命令执行的,请确保您以该--no-debug标志启动它
在我的项目中使用导入命令运行良好,尽管它没有实现完全的内存中立性,但剩余的泄漏可以忽略不计。也许这对你的情况有帮助。