When building a new PHP application with Doctrine (doctrine/orm 2.7.4), our team discovered that in some long-running commands memory usage was building up.
We went through the basic checklist:
- Application is running in production mode - our experience has shown, when is not, then Doctrine SQL logger could eat up memory - checked.
- Doctrine clear is called regularly - when it's not, then objects persist in Doctrine internal in-memory cache - checked.
- No other code in our application was not obviously building its own memory cache - checked.
Due to the amount of data generated by the long-running process, we weren't able to use obvious choices as Blackfire.
After a little googling we decided to use php-memprof as a tool to collect data. Sadly there was no expert to take to read KCacheGrind so we dumped data as an array using memprof_dump_array
and find by analysing output that memory is building up somewhere in Doctrine.
After good old-fashioned "comment out some code to see if the error disappears" we discovered that the memory was building up due to usage of Doctrine\ORM:Query::getOneOrNullResult
in our shared library.
The memory leak was tough so subtle, that it increased only ~20MB on every thousand calls.
After changing getOneOrNullResult to execute memory leak disappeared.
Our application is now working smoothly but the problem in Doctrine still needs to be tracked down.
Top comments (1)
I think
getOneOrNullResult
returns an entity object that is managed by the entity manager. So, it will instantiate an additional memory for the entity until you clear or detach it from entity manager.