views:

1881

answers:

6

Doctrine appears to be taking well over 4MB of RAM to execute a single, simple query:

print memory_get_peak_usage()." <br>\n";
$q = Doctrine_Query::create()
    ->from('Directories d')
    ->where('d.DIRECTORY_ID = ?', 5);

$dir = $q->fetchOne();
print $dir['name']." ".$dir['description']."<br>\n";

print memory_get_peak_usage()." <br>\n";

/***************  OUTPUT:  **************************

6393616
testname testdescription
10999648

/***************************************************/

This is on a test database with very little data in it - the item that I am querying doesn't contain any data other than what is displayed here.

Is there potentially something wrong with the way I have the system set up, or is this standard memory usage for Doctrine?

+2  A: 

Hi,

From what I can see, you code doesn't seem to be wrong...


As a test, I've set up a quick example, with a very simple table (only four fields).

Here is the relevant code :

var_dump(number_format(memory_get_peak_usage()));

$test = Doctrine::getTable('Test')->find(1);

var_dump(number_format(memory_get_peak_usage()));

When doing that, I have this kind of output :

string '1,316,088' (length=9)
string '2,148,760' (length=9)

Considering the table is really simple and that I am only fetching one line, it seems "much" to me too -- but that's quite consistent with what you are getting, and with what I saw on other projects :-(


If you only need to display your data, and not work with it (ie update/delete/...), a solution might be to not fetch complex objects, but only a simple array :

$test = Doctrine::getTable('Test')->find(1, Doctrine::HYDRATE_ARRAY);

But, in this case, it doesn't make much of a difference, actually :-( :

string '1,316,424' (length=9)
string '2,107,128' (length=9)

Only 40 KB of difference -- well, with bigger objects / more lines, it might still be a good idea...


In the Doctrine manual, there is a page called Improving Performance ; maybe it could help you, especially for these sections :


Oh, btw : I did this test on PHP 5.3.0 ; maybe this can have an impact on the amount of memory used...

Pascal MARTIN
This worries me, as I'm integrating Doctrine into my framework.
Arms
Before worrying too much, you might want to do some more tests, with bigger tables, more data, and all that -- to see if the memory increase is linear or not. ;; btw : I've seen Doctrine use in projects based on both Zend Framework and Symfony, and this has never been a problem...
Pascal MARTIN
Pascal MARTIN: Perhaps these sites you know of don't have heavy loads? I'd like to know if any major sites are using Doctrine.
Fragsworth
David
+3  A: 

Well, where does this memory usage come from? As Pascal MARTIN pointed out, array hydration does not make a great difference which is logical concerning that we're only talking about a few records here.

The memory consumption comes from all the classes that are loaded on demand through autoloading.

If you dont have APC set up, then yes, there is something wrong with the way your system is set up. Dont even start to measure performance and expect good results with any large php library without an opcode cache like APC. It will not only speed up the execution but also reduce memory usage by at least 50% on all page loads except the very first one (where APC needs to cache the bytecodes first).

And 4MB with your simple example really smells like no-APC, otherwise it would really be a bit high.

+3  A: 

I agree with romanb's answer - using an OpCode cache is a definite must when using large libs/frameworks.

An example related to OpCode caching

I've recently adopted Doctrine usage with Zend Framework and was curious about memory usage - so like the OP, I created a method using similar criteria to the OPs test and ran it as an overall test to see what ZF + Doctrine's peak memory usage would be.

I got the following results:

Result without APC:

10.25 megabytes
RV David
16.5 megabytes

Result with APC:

3 megabytes
RV David
4.25 megabytes

Opcode caching makes a very significant difference.

rvdavid
A: 

Doctrine provides a free() function on Doctrine_Record, Doctrine_Collection, and Doctrine_Query which eliminates the circular references on those objects, freeing them up for garbage collection. More info..

To make memory usage a little bit less You can try to use folowing code:

  • $record->free(true) – will do deep free-up's, calls free() on all relations too
  • $collection->free() – this will free all collection references
  • Doctrine_Manager::connection()->clean()/clear() – cleanup connection (and remove identity map entries)
  • $query->free()
liutis
+1  A: 

I would guess that most of that memory is used up loading Doctrine's classes, not actually for objects associated with the query itself.

  • Which version of Doctrine are you using?
  • Are you using the autoloader?

In Doctrine 1.1, the default autoload behavior is called 'aggressive', which means that it load all of your model classes even if you're only using one or two on any particular request. Setting that behavior to 'conservative' would reduce memory usage.

mehaase
A: 

I have just did "daemonized" script with symfony 1.4 and setting the following stopped the memory hogging:

sfConfig::set('sf_debug', false);
Ikon