Egon Olieux
Egon Olieux

Reputation: 759

Doctrine 2: memory leak when removing and flushing entity in preflush event

I have an entity X which contains a collection of Y entities. The Y entities are "privately owned" by entity X, which means that when an Y entity is removed from the collection, it should be completely removed from the database.

Normally, this can be achieved using orphanRemoval, but because of the standard flushing order (collection inserts before collection updates before collection deletions), a unique constraint on the Y entity is destined to fail if a new or updated item has the same values as a deleted item.

To tackle this issue, I manually keep track of removed Y entities from the collection by storing them in a separate array (without using orphanRemoval):

public function removeY(Y $y) : X
{
    $y->setX(null);
    $this->removedYItems[] = $y;
    $this->yCollection->removeElement($y);
    return $this;
}

When a flush operation is called, I manually commit the removed items in a preFlush event:

/**
 * @ORM\PreFlush
 */
public function onPreFlush(PreFlushEventArgs $eventArgs) : void
{
    if (count($this->removedYItems) === 0)
    {
        return;
    }

    $entityManager = $eventArgs->getEntityManager();

    foreach ($this->removedYItems as $removedYItem)
    {
        $entityManager->remove($removedYItem);
    }

    $entityManager->flush();
}

At the end I explicitly call flush to ensure the items are removed from the database before any updates or insertions.

However, after calling the flush operation the web page seems to hang and when I look at my server logs, PHP seems to have run out of memory (1GiB):

[Sat Nov 25 00:32:14.016294 2017] [php7:error] [pid 22212] [client 192.168.0.1:59174] PHP Fatal error:  Allowed memory size of 1073741824 bytes exhausted (tried to allocate 262144 bytes) in Unknown on line 0

Is this a (known) Doctrine bug causing a memory leak? Or am I not supposed to call flush in a preFlush event (the documentation says otherwise: http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preflush)?

I am running PHP 7.1.11 on FreeBSD 11.0 STABLE with Doctrine 2.5.9. I'll try to test this on another machine as soon as possible.

Upvotes: 0

Views: 1057

Answers (2)

Egon Olieux
Egon Olieux

Reputation: 759

After doing some tests, it seems the preFlush event is stuck in an infinite recursive loop (as hinted by @geolim4). I created an issue in the Doctrine repository on GitHub asking for clarification, and they told me this is a mistake in the documentation: https://github.com/doctrine/doctrine2/issues/6857.

Upvotes: 0

Geolim4
Geolim4

Reputation: 454

If you are working with profiler enabled, turn it off for Doctrine. See how to do it here. Sf Profiler is known to be very memory-greedy when working with a bunch of entities.

Upvotes: 0

Related Questions