I'm using Symfony 1.4 and Doctrine.
So far I had no problem running tasks with Symfony. But now that I have to import a pretty big amount of data and save them in the database, I get the infamous
"Fatal Error: Allowed memory size of XXXX bytes exhausted"
During this import I'm only creating new objects, setting a few fields and saving them.
I'm pretty sure it has something to do with the number of objects I'm creating when saving data. Unsetting those objects doesn't do anything though.
Are there any best practices to limit memory usage in Symfony?
I've come across this, and there's a couple of techniques I found really helped with Doctrine's extensive memory usage.
1: Where possible, hydrate your Doctrine query results down to an array. You can do this as follows eg:
$query = self::createQuery("q")->
...
->setHydrationMode(Doctrine::HYDRATE_ARRAY)
->execute();
This forces Doctrine to NOT create large objects, but instead reduces it to an array. Obviously bear in mind that if you do this, you lose the ability to call methods etc, so this is only good if you're using it for reading field values etc.
2: Free your results after execution. This is documented in a tiny area of the Doctrine docs, but it's really helped out the import task I was using:
$query->free();
That's it. You can also do this on objects that you've created, eg $myObj->free();
and this forces Doctrine to remove all the circular references that it creates. Note that circular references are automatically freed from PHP 5.3 onwards on deletion of an object via the PHP scope or unset()
, but before that you'll need to do it yourself.
Unsetting variables after you've used them also helps, although do this in conjunction with the free()
method above as mentioned, as unset()
won't clear the circular refs otherwise.
Try this :
Doctrine_Manager::connection()->setAttribute(Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS, true );
as mentioned on
php/symfony/doctrine memory leak?
Answer from Jordan Feldstein not mine.
Another hint for reducing the amount of memory used inside a task is to disable the query profiler. A big number of queries tends to make the task using more and more memory.
To do so create a new task environment in your database.yml config file by adding the following lines:
task:
doctrine:
class: sfDoctrineDatabase
param:
profiler: false
Then setup your task to run in "task" environment. It should help to keep memory usage stable if your queries are in a loop.
Sorry I know this is a late answer, but could help someone.
Another potentially huge memory saver is to make sure Symfony's debug mode is not enabled for that task. In a couple of long-running tasks I added this line and it cut down the RAM usage about 40% even after I had optimized things like hydration mode.
sfConfig::set('sf_debug', false);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With