vejez progresiva perdida niños memoria los diagnosticar curar como adolescencia php memory-leaks reference-counting

php - progresiva - perdida de memoria en niños



Cómo solucionar una pérdida de memoria en PHP (8)

Mi aplicación PHP tiene un script de importación que puede importar registros.

En este momento, se está importando desde un archivo CSV. Está leyendo cada línea del archivo CSV, una línea a la vez usando fgetcsv, y para cada línea está procesando mucho ese registro, incluidas las consultas de la base de datos, y luego pasa a la siguiente línea. No debería tener que seguir acumulando más memoria.

Después de alrededor de 2500 registros importados, PHP muere, diciendo que se ha excedido en su límite de memoria (132 MB aproximadamente).

El archivo CSV en sí es solo un par de megas, el otro procesamiento que ocurre es un montón de comparaciones de cadenas, diferencias, etc. Tengo una gran cantidad de código operando y sería difícil encontrar una "reproducción más pequeña". muestra''.

¿Cuáles son algunas buenas maneras de encontrar y solucionar este problema?

Causa del problema encontrado

Tengo una clase de depuración que registra todas mis consultas de base de datos durante el tiempo de ejecución. Así que esas cadenas de SQL, de unos 30KB de largo, se quedaron en la memoria. Me doy cuenta de que esto no es adecuado para scripts diseñados para ejecutarse durante mucho tiempo.

Puede haber otras fuentes de pérdidas de memoria, pero estoy bastante seguro de que esta es la causa de mi problema.


¿Cómo estás leyendo el archivo? Si utiliza fread / filegetcontents u otras funciones similares, va a consumir todo el tamaño del archivo (o la cantidad de carga que tenga con fread) en la memoria, ya que todo el archivo se carga en el momento de la llamada. Sin embargo, si usa fgetcsv si solo leerá una línea a la vez, dependiendo de la longitud de la línea, esto puede ser dramáticamente más fácil en su memoria.

Asegúrese también de que está reutilizando tantas variables como sea posible en cada ciclo. Compruebe que no haya ninguna matriz con grandes cantidades de datos en ellos.

Como última nota, también asegúrese de que está abriendo su archivo antes de su bucle y luego cerrándolo después:

$fh = fopen(...); while(true) { //... } fclose($fh);

Realmente no quieres estar haciendo esto:

while(true) { $fh = fopen(...); //... fclose($fh); }

Y como han dicho otros, será difícil saberlo sin ver un código.



Depende de cómo se borran las variables después de terminar con ellas.

Parece que ha terminado con el registro pero todavía está almacenando la información en algún lugar. Use unset() para borrar las variables en caso de duda.

Proporcione un ejemplo de código de reproducción mínima para ver a dónde va toda esa memoria si esto no ayuda.

Por cierto, producir el ejemplo de código más pequeño que reproduzca el problema es una excelente técnica de depuración porque lo obliga a revisar el código nuevamente, con cuidado.


Es difícil decir la causa sin ver ningún código. Sin embargo, un problema típico son las referencias recursivas, es decir. el objeto A apunta al objeto B y al revés, lo que puede hacer que el GC se estropee.

No sé cómo está procesando el archivo actualmente, pero podría intentar leer el archivo solo una fila a la vez. Si lees todo el archivo a la vez puede consumir más memoria.

Esta es en realidad una de las razones por las que a menudo prefiero Python para las tareas de procesamiento por lotes.


Estaba teniendo el mismo problema, y ​​también se debía a la creación de perfiles de la base de datos (Zend_Db_Profiler_Firebug). En mi caso estaba goteando 1mb por minuto. se suponía que esta secuencia de comandos se ejecutaría durante días, por lo que se bloquearía en unas pocas horas.


Le ayudaría echar un vistazo al código, pero si desea depurarlo usted mismo, eche un vistazo a Xdebug , esto le ayudará a perfilar su aplicación.

Por supuesto, dependiendo de lo que esté haciendo, es posible que esté acumulando algo de memoria, aunque 132MB parece ya alto para 2500 registros. Por supuesto, puede modificar su límite de memoria en php.ini si es necesario.

¿Qué tamaño tiene el archivo CSV que estás leyendo? ¿Y qué objetos y tipo de procesamiento le estás haciendo?


Si, de hecho, sospecha que solo hay una o dos fugas de memoria en su script que están causando que se bloquee, entonces debe seguir los siguientes pasos:

  • Cambie memory_limit a algo pequeño, como 500KB
  • Comente todos menos uno de los pasos de procesamiento que se aplican a cada fila.
  • Ejecute el procesamiento limitado en todo el archivo CSV y vea si puede completarse.
  • Poco a poco agregue más pasos de nuevo y mire para ver si el uso de memoria aumenta.

Ejemplo:

ini_set(''memory_limit'', 1024 * 500); $fp = fopen("test.csv", ''r''); while($row = fgetcsv($fp)) { validate_row($row); // step 1: validate // add these back in one by one and keep an eye on memory usage //calculate_fizz($row); // step 2: fizz //calculate_buzz($row); // step 3: buzz //triangulate($row); // step 4: triangulate } echo "Memory used: ", memory_get_peak_usage(), "/n";

El peor de los casos es que todos sus pasos de procesamiento son moderadamente ineficientes y tendrá que optimizarlos todos.


puede intentar una instalación local de php5.3 y llamar a http://www.php.net/manual/en/function.gc-collect-cycles.php.

gc_collect_cycles - gc_collect_cycles fuerzas de cualquier ciclo de basura existente

si la situación mejora, al menos verificaste (en) el (los) problema (s).