generate create php memory-leaks symfony1 doctrine

php - create - symfony 4 doctrine



php/symfony/doctrine escape de memoria? (9)

Estoy teniendo problemas con una inserción por lotes de objetos en una base de datos utilizando Symfony 1.4 y la doctrina 1.2.

Mi modelo tiene un cierto tipo de objeto llamado "Sector", cada uno de los cuales tiene varios objetos de tipo "Cupo" (que generalmente van desde 50 hasta 200000). Estos objetos son bastante pequeños; solo una cadena de identificador corta y uno o dos enteros. Cuando el usuario crea un grupo de sectores, debo agregar automáticamente todas estas instancias de "Cupo" a la base de datos. En caso de que algo salga mal, estoy usando una transacción de doctrina para deshacer todo. El problema es que solo puedo crear alrededor de 2000 instancias antes de que php se quede sin memoria. Actualmente tiene un límite de 128 MB, que debería ser más que suficiente para manejar objetos que utilizan menos de 100 bytes. He intentado aumentar el límite de memoria hasta 512 MB, pero php aún falla y eso no resuelve el problema. ¿Estoy haciendo la inserción por lotes correctamente o hay una mejor manera?

Aquí está el error:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 71 bytes) in /Users/yo/Sites/grifoo/lib/vendor/symfony/lib/log/sfVarLogger.class.php on line 170

Y aquí está el código:

public function save($conn=null){ $conn=$conn?$conn:Doctrine_Manager::connection(); $conn->beginTransaction(); try { $evento=$this->object; foreach($evento->getSectores() as $s){ for($j=0;$j<$s->getCapacity();$j++){ $cupo=new Cupo(); $cupo->setActivo($s->getActivo()); $cupo->setEventoId($s->getEventoId()); $cupo->setNombre($j); $cupo->setSector($s); $cupo->save(); } } $conn->commit(); return; } catch (Exception $e) { $conn->rollback(); throw $e; }

Una vez más, este código funciona bien para menos de 1000 objetos, pero cualquier cosa mayor que 1500 falla. Gracias por la ayuda.


Acabo de hacer un script "daemonized" con Symfony 1.4 y al configurar lo siguiente se detuvo el acaparamiento de memoria:

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


Cierre y vuelva a abrir la conexión periódicamente, no estoy seguro de por qué, pero parece que PDO conserva las referencias.


Intenta unset($cupo); después de cada ahorro. Esto debería ser de ayuda. Otra cosa es dividir el script y hacer un procesamiento por lotes.


La doctrina gotea y no hay mucho que puedas hacer al respecto. Asegúrese de usar $ q-> free () cuando corresponda para minimizar el efecto. La doctrina no es para los guiones de mantenimiento. La única forma de solucionar este problema es dividir su secuencia de comandos en partes que realizarán parte de la tarea. Una forma de hacerlo es agregar un parámetro de inicio a su secuencia de comandos y después de que se haya procesado una cierta cantidad de objetos, la secuencia de comandos se redirige a sí misma con un valor de inicio más alto. Esto funciona bien para mí, aunque hace que escribir guiones de mantenimiento sea más engorroso.


Lo que funciona para mí es llamar al método free como este:

$cupo->save(); $cupo->free(true); // free also the related components unset($cupo);


Para mí, acabo de inicializar la tarea así:

// initialize the database connection $databaseManager = new sfDatabaseManager($this->configuration); $connection = $databaseManager->getDatabase($options[''connection''])->getConnection(); $config = ProjectConfiguration::getApplicationConfiguration(''frontend'', ''prod'', true); sfContext::createInstance($config);

(CON CONFIG. PROD)
y use free () después de un save () en el objeto de doctrine

la memoria es estable a 25Mo

memory_get_usage=26.884071350098Mo

con php 5.3 en debian squeeze


Para una tarea de Symfony, también me enfrenté a este problema y hice lo siguiente. Funciono para mi

  • Deshabilitar el modo de depuración. Añadir siguiente antes de inicializar la conexión db

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

  • Establecer atributo de auto consulta objeto libre para la conexión de db

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

  • Libera todos los objetos después de su uso

    $object_name->free()

  • Desactive todas las matrices después de usar unset($array_name)

  • Revise todas las consultas de doctrina utilizadas en la tarea. Libera todas las consultas después de su uso. $q->free() (Esta es una buena práctica para cualquier momento de consulta usando).

Eso es todo. Espero que pueda ayudar a alguien.


Tratado de hacer

$cupo->save(); $cupo->free(); $cupo = null;

(Pero sustituyendo mi código) Y sigo teniendo desbordamientos de memoria. ¿Alguna otra idea, así que?

Actualizar:

Creé un nuevo entorno en mi database.yml, que se parece a:

all: doctrine: class: sfDoctrineDatabase param: dsn: ''mysql:host=localhost;dbname=.......'' username: ..... password: ..... profiler: false

El generador de perfiles: entrada falsa deshabilita el registro de consultas de doctrine, que normalmente conserva una copia de cada consulta que realice. No detuvo la pérdida de memoria, pero pude llegar a casi el doble de la importación de datos que sin ella.

Actualización 2

yo añadí

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

Antes de ejecutar mis consultas, y cambiaron.

$cupo = null;

a

unset($cupo);

Y ahora mi guión se ha estado batiendo alegremente. Estoy bastante seguro de que terminará sin quedarse sin RAM esta vez.

Actualización 3

Sip. Ese es el combo ganador.


Trate de romper la referencia circular que generalmente causa pérdidas de memoria con

$cupo->save(); $cupo->free(); //this call

como se described en el manual de Doctrine.