2009-09-11 15 views
10

Doctrina parece estar tomando más de 4 MB de memoria RAM para ejecutar una única, simple consulta:Doctrina uso de memoria consulta

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 

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

Se trata de una base de datos de prueba con muy pocos datos en él - el elemento que soy consulta no contiene ningún otro dato que no sea el que se muestra aquí.

¿Hay algún problema potencial con la forma en que configuro el sistema, o es este uso de memoria estándar para Doctrine?

Respuesta

6

Por lo que puedo ver, el código no parece estar mal ...


Como prueba, He configurado un ejemplo rápido, con una mesa muy simple (sólo cuatro campos).

Aquí está el código correspondiente:

var_dump(number_format(memory_get_peak_usage())); 

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

var_dump(number_format(memory_get_peak_usage())); 

Al hacer eso, no tengo este tipo de salida:

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

Teniendo en cuenta la tabla es muy simple y que yo no soy más que recuperar una línea, me parece "mucho" también, pero eso es bastante consistente con lo que está obteniendo, y con lo que vi en otros proyectos :-(


Si sólo necesita para mostrar los datos, y no trabajar con él (es decir, actualizar/borrar/...), una solución podría ser la de no recupera objetos complejos, pero sólo en una matriz sencilla:

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

Pero , en este caso, no hace mucha diferencia, en realidad :-(:

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

Sólo 40 KB de diferencia - bueno, con grandes objetos/más líneas, aún podría ser una buena idea ...


En el manual de Doctrine, hay una página llamada Improving Performance; tal vez podría ayudarle, especialmente para estas secciones:


Ah, por cierto: Hice esta prueba en PHP 5.3.0; tal vez esto puede tener un impacto en la cantidad de memoria utilizada ...

+0

Esto me preocupa, ya que estoy integrando Doctrine en mi framework. –

+0

Antes de preocuparse demasiado, es posible que desee realizar más pruebas, con tablas más grandes, más datos y todo eso, para ver si el aumento de la memoria es lineal o no. ;; BTW: He visto el uso de Doctrine en proyectos basados ​​en Zend Framework y Symfony, y esto nunca ha sido un problema ... –

+0

Pascal MARTIN: ¿Quizás estos sitios que conoces no tienen cargas pesadas? Me gustaría saber si algún sitio importante está usando Doctrine. – Fragsworth

4

Bueno, ¿de dónde viene este uso de la memoria? Como señaló Pascal MARTIN, la hidratación de la matriz no hace una gran diferencia, lo cual es lógico, ya que solo estamos hablando de unos pocos registros aquí.

El consumo de memoria proviene de todas las clases cargadas bajo demanda mediante carga automática.

Si no tiene la configuración de APC, entonces sí, hay algún problema con la configuración de su sistema. Ni siquiera comience a medir el rendimiento y espere buenos resultados con cualquier biblioteca php grande sin un caché de código de operación como APC.No solo acelerará la ejecución, sino que también reducirá el uso de la memoria al menos en un 50% en todas las cargas de página, excepto en la primera (donde APC necesita almacenar primero los códigos de byte).

Y 4MB con su ejemplo simple realmente huele a no-APC, de lo contrario, sería realmente un poco alto.

5

Estoy de acuerdo con la respuesta de romanb: el uso de una caché de OpCode es una necesidad absoluta cuando se utilizan libs/frameworks de gran tamaño.

Un ejemplo relacionado con el almacenamiento en caché código de operación

He recientemente adoptado el uso Doctrina con Zend Framework y tenía curiosidad sobre el uso de memoria - así como el PO, he creado un método de acuerdo con criterios similares a la prueba de los PO y lo ejecutó como una prueba general para ver cuál sería el uso máximo de memoria de ZF + Doctrine.

Me dieron los siguientes resultados:

resultado sin APC:

10.25 megabytes 
RV David 
16.5 megabytes 

resultado con APC:

3 megabytes 
RV David 
4.25 megabytes 

Código de Operación de almacenamiento en caché hace una diferencia muy significativa.

2

Doctrine proporciona una función gratuita() en Doctrine_Record, Doctrine_Collection y Doctrine_Query que elimina las referencias circulares en esos objetos, liberándolos para la recolección de elementos no utilizados. More info..

Para hacer uso de la memoria un poco menos Usted puede tratar de usar el código folowing:

  • $ Registro> libre (verdadera) - va a hacer profundas de forma gratuita en marcha, llamadas gratis() en todos las relaciones demasiado
  • $ colección-> libre() - esto va a liberar toda la colección hace referencia a
  • Doctrine_Manager :: conexión() -> limpia()/clear() - conexión de la limpieza (y eliminar entradas del mapa de identidad)
  • $ query-> free()
1

Supongo que la mayor parte de esa memoria se utiliza para cargar las clases de Doctrine, no para los objetos asociados con la consulta en sí.

  • ¿Qué versión de Doctrine estás utilizando?
  • ¿Está utilizando el autocargador?

En Doctrina 1.1, el comportamiento por defecto de carga automática se llama 'agresivo', lo que significa que cargar todas las clases del modelo, incluso si sólo está utilizando uno o dos en cualquier solicitud particular. Establecer ese comportamiento en 'conservador' reduciría el uso de memoria.

0

he acabo de hacer "endemoniada" guión con Symfony 1.4 y el establecimiento de la siguiente detuvo la memoria acaparando:

sfConfig::set('sf_debug', false); 
+0

Esto es bueno si usa doctrina + Symfony, pero no ayudará si solo está usando Doctrine. –

+0

Estoy de acuerdo con Ikon, en Symfony, Profiler Gobals, Ram. entonces: 'sfConfig :: set ('sf_debug', false);' ** ANTES ** la conexión de la Base de Datos está hecha ayudará considerablemente espacilly si, como yo, usted está volcando tablas grandes a csv. es posible que desee hacer esto en * frontend_dev.php * o similar (3er parámetro). –

4

Precaución con fetchOne() en la Doctrina de consulta.Esta llamada de función no añadir "Límite 1" en SQL

Si sólo tiene que conseguir uno de los registros de base de datos, asegúrese de que:

$q->limit(1)->fetchOne() 

El uso de memoria es tremendo caer sobre una mesa grande.

Puede ver que fetchOne() buscará primero DB como una colección y luego devolverá el primer elemento.

public function fetchOne($params = array(), $hydrationMode = null) 
{ 
    $collection = $this->execute($params, $hydrationMode); 

    if (is_scalar($collection)) { 
     return $collection; 
    } 

    if (count($collection) === 0) { 
     return false; 
    } 

    if ($collection instanceof Doctrine_Collection) { 
     return $collection->getFirst(); 
    } else if (is_array($collection)) { 
     return array_shift($collection); 
    } 

    return false; 
}