php memory symfony1 doctrine symfony-1.4

php - ¿Cómo usar menos memoria mientras ejecutas una tarea en Symfony 1.4?



memory symfony1 (8)

He tenido el mismo problema con los trabajos por lotes de PHP para Symfony: si se ejecutan durante mucho tiempo y usan una gran cantidad de datos, tienden a aumentar, e incluso si hice un contenedor que invocó muchos procesos PHP separados, no sucedió. t ayuda

Debido a esto, he reescrito mis trabajos por lotes más grandes con DBI de Perl y son confiables y manejables.

No estoy sugiriendo que esta sea la mejor respuesta, solo simpatizo y ofrezco mi experiencia. Probablemente hay una manera de hacer que PHP se comporte mejor.

Estoy usando Symfony 1.4 y Doctrine.

Hasta ahora no he tenido problemas para ejecutar tareas con Symfony. Pero ahora que tengo que importar una gran cantidad de datos y guardarlos en la base de datos, obtengo el infame

"Error grave: tamaño de memoria permitido de XXXX bytes agotado"

Durante esta importación solo estoy creando nuevos objetos, configurando algunos campos y guardándolos.

Estoy bastante seguro de que tiene algo que ver con la cantidad de objetos que estoy creando al guardar datos. Sin embargo, desarmar esos objetos no hace nada.

¿Existen prácticas recomendadas para limitar el uso de memoria en Symfony?


Lo siento, sé que esta es una respuesta tardía, pero podría ayudar a alguien.

Otro ahorro de memoria potencialmente enorme es asegurarse de que el modo de depuración de Symfony no esté habilitado para esa tarea. En un par de tareas de larga duración, agregué esta línea y redujo el uso de RAM en un 40%, incluso después de haber optimizado cosas como el modo de hidratación.

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


Me he encontrado con esto, y hay un par de técnicas que realmente ayudaron con el uso extensivo de la memoria de Doctrine.

1: Cuando sea posible, hidrate los resultados de la consulta de Doctrine en una matriz. Puede hacerlo de la siguiente manera, por ejemplo:

$query = self::createQuery("q")-> ... ->setHydrationMode(Doctrine::HYDRATE_ARRAY) ->execute();

Esto obliga a Doctrine a NO crear objetos grandes, sino que lo reduce a una matriz. Obviamente, tenga en cuenta que si hace esto, perderá la capacidad de llamar a métodos, etc., así que esto solo es bueno si lo está utilizando para leer valores de campo, etc.

2: Libera tus resultados después de la ejecución. Esto está documentado en una pequeña área de los documentos de Doctrine, pero realmente ayudó a la tarea de importación que estaba usando:

$query->free();

Eso es. También puede hacer esto en los objetos que ha creado, por ejemplo, $myObj->free(); y esto obliga a Doctrine a eliminar todas las referencias circulares que crea. Tenga en cuenta que las referencias circulares se liberan automáticamente de PHP 5.3 en adelante al eliminar un objeto a través del alcance de PHP o unset() , pero antes de eso deberá hacerlo usted mismo.

Desactivar las variables después de haberlas usado también ayuda, aunque haga esto en conjunto con el método free() mencionado anteriormente, ya que unset() no borrará las referencias circulares de lo contrario.


Otra sugerencia para reducir la cantidad de memoria utilizada en una tarea es deshabilitar el generador de perfiles de consultas. Un gran número de consultas tiende a hacer que la tarea utilice más y más memoria.

Para ello, cree un nuevo entorno de tareas en su archivo de configuración database.yml agregando las siguientes líneas:

task: doctrine: class: sfDoctrineDatabase param: profiler: false

Luego configura tu tarea para que se ejecute en el entorno de "tarea". Debería ayudar a mantener estable el uso de memoria si sus consultas están en un bucle.


Precaución con fetchOne () en Doctrine Query. Esta llamada de función no anexará "Límite 1" en SQL

Si solo necesita obtener un registro de DB, asegúrese de:

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

El uso de la memoria es tremenda caída en la mesa grande.

Podría ver que fetchOne () se recuperará de la base de datos como una colección primero 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; }


Prueba esto :

Doctrine_Manager::connection()->setAttribute(Doctrine_Core::ATTR_AUTO_FREE_QUERY_OBJECTS, true );

como se menciona en

php / symfony / doctrine escape de memoria?

La respuesta de Jordan Feldstein no es mía.


También intente limitar los campos (seleccionar) en su consulta solo a aquellos que realmente necesita.

por ejemplo usa algo como:

$query = self::createQuery("q")-> ->select(''id'',''title'',''price'') ...

en lugar de:

$query = self::createQuery("q")-> ->select(''*'') ...