¿Cómo encontrar qué script PHP está perdiendo memoria?

Mi servidor dedicado tiene 32GB de RAM y la memoria simplemente sube y sube constantemente y tengo que reiniciarlo todos los días. Esto me está costando clientes y dinero.

Me está costando encontrar dónde está la fuga de memoria. Todo lo que puedo encontrar en línea es que la gente diga “Usar xdebug”, pero no he podido encontrar ningún tutorial de xdebug para encontrar memory leaks. He intentado imprimir memory_get_usage antes y después de las llamadas a funciones, pero ¿es esa la forma correcta de hacerlo?

Tengo MUCHOS scripts php en ejecución, algunos de visitantes, otros de cron jobs, y necesito encontrar cuál (es) de ellos está filtrando memoria y corregirlo lo antes posible, pero ni siquiera sé cómo determinar si una función dada es goteando memoria o no.

Intenté imprimir memory_get_usage antes de una llamada de función y después, y sube, pero luego si llamo a la función más de una vez, ya no sube. ¿Puede alguien explicar esto y decirme cómo puedo decir de manera simple y sencilla si una función de PHP tiene una pérdida de memoria?

Podrías hacer varias cosas, pero primero deberías tratar de evitar la creación de pérdidas de memoria en primer lugar.

Permítanme aclarar: PHP es un lenguaje de scripting y no está diseñado para scripts de larga ejecución, por lo que su administración de memoria no es la mejor en el mercado. Pero, ¿por qué debería ser? Su propósito es ser llamado en un nivel de solicitud, por lo que su ámbito de ejecución es bastante pequeño (no más de 2 a 3 segundos). Todo lo demás debería ponerse en segundo plano.

¿Qué puedo hacer contra las memory leaks?

  1. Si se encuentra en una versión por debajo de 5.4, debe tener en cuenta las referencias circulares, ya que no se trata de basura.

  2. Si necesita que un script se ejecute continuamente, puede pensar en un enfoque diferente. Intente una implementación while(true) , pero envuelva al supervisor ( http://supervisord.org ) alrededor de su script, y déjelo que se llame después de que termine. De esta forma, estarás 100% seguro de que nunca tendrás pérdidas de memoria.

  3. Podría usar xdebug para perfilar sus guiones uno por uno y descubrir dónde se consume mucha memoria.

  4. Podrías implementar un destructor para desarmar todas tus referencias si la clase ya no es necesaria.

     public function __destruct(){ $this->cleanup(); } public function cleanup() { //cleanup everything from attributes foreach (get_class_vars(__CLASS__) as $clsVar => $_) { unset($this->$clsVar); } //cleanup all objects inside data array if (is_array($this->_data)) { foreach ($this->_data as $value) { if (is_object($value) && method_exists($value, 'cleanUp')) { $value->cleanUp(); } } } } 
  5. Lea la documentación de PHP con respecto a la recolección de basura http://us3.php.net/manual/en/features.gc.php

  6. Evite las variables globales, porque nunca se recogen basura y deben unset explícitamente. Si está utilizando un Framework como ZF o Symfony que podría no ser posible, ya que rompería la funcionalidad si lo hace.

Por último, pero no menos importante, quiero enfatizar una vez más que PHP no es adecuado para scripts de larga ejecución. Si tiene cosas que hacer, que deben ejecutarse continuamente, no debe desmoronarse con memory leaks en PHP, pero tómese el tiempo para aprender un lenguaje más sofisticado como JAVA o C #.

Mire esta extensión php: https://github.com/arnaud-lb/php-memory-profiler . Podrá descargar información en diferentes formatos y analizarla de manera sencilla con algunas herramientas, como Google Performance Tools , KCacheGrind o QCacheGrind .

Encontré método que funciona bastante bien para mí:

  1. Instalar la extensión ” php-memprof “. En usted puede ejecutar Ubuntu:

    sudo pecl install memprof

  2. Instalar ” google-perftools “. Nuevamente para Ubuntu:

    sudo apt-get install google-perftools

  3. Agregue este código al comienzo de su script:

     if (function_exists('memprof_enable')) { memprof_enable(); } 
  4. Y este aroud lugar donde esperabas encontrar la pérdida de memoria:

     if (function_exists("memprof_dump_pprof")) { $time = microtime(true); $f = fopen("/tmp/profile_$time.heap", "w"); memprof_dump_pprof($f); fclose($f); echo "Memory profile dumped. "; } 

    En mi caso, estaba dentro de un ciclo grande cada 100 carreras.

  5. Ejecute google-pprof comparando 2 volcados de memoria:

     google-pprof --web --base=/tmp/profile_17.heap /tmp/profile_18.heap 

    Esto abrirá una imagen svg como esta en su navegador:

    muestra del documento

    Descripción de los números y nombres dentro de usted puede encontrar en la documentación de gperftools

Las fugas en la reparación de PS en php-level no le garantizarán que no haya memory leaks en el intérprete. En mi caso, termino solo con reiniciar sctipt en periodos más largos.

No soy un experto en el uso de la memoria, pero tal vez este método te ayude a detectar los scripts problemáticos:

Obtenga información: 1. Use los archivos de registro de acceso de apache 2. Cree su propio archivo de registro de uso de memoria ( http://www.webhostingtalk.com/showthread.php?t=617742 )

Compruebe la hora en que el uso de la memoria aumenta y compare con el registro de acceso de apache.

Al menos, le dará información sobre si el uso aumenta de forma lenta y constante o si comienza en cierto punto.

¡Buena suerte!