todas - Seguimiento del uso de la memoria en PHP
strip_tags() (4)
Estoy intentando rastrear el uso de memoria de un script que procesa URLs. La idea básica es verificar que haya un búfer razonable antes de agregar otra URL a un controlador múltiple cURL. Estoy usando un concepto ''rolling cURL'' que procesa los datos de una URL mientras se ejecuta el controlador múltiple. Esto significa que puedo mantener activas las conexiones de N agregando una nueva URL de un grupo cada vez que una URL existente procesa y se elimina.
He usado memory_get_usage()
con algunos resultados positivos. Agregar la bandera real_usage
ayudó (no es muy claro en la diferencia entre la memoria ''sistema'' y la memoria ''emalloc'', pero el sistema muestra números más grandes). memory_get_usage()
aumenta cuando las URL se agregan y luego se reducen a medida que se agota el conjunto de URL. Sin embargo, acabo de exceder el límite de 32M con mi última verificación de memoria siendo ~ 18M.
Encuence el uso de la memoria cada vez que cULL múltiples señales ha devuelto una solicitud. Dado que varias solicitudes pueden regresar al mismo tiempo, existe la posibilidad de que un grupo de URL devolviera datos al mismo tiempo y, de hecho, aumentó el uso de la memoria en 14 millones. Sin embargo, si memory_get_usage()
es precisa, creo que eso es lo que está sucediendo.
[ Actualización : debería haber ejecutado más pruebas antes de preguntar, supongo, aumentó el límite de memoria de php (pero dejó la cantidad ''segura'' de la misma en el script) y el uso de memoria como se informó saltó desde debajo de mi límite autoimpuesto de 25M a más de 32M . Luego, como se esperaba, disminuyó lentamente a medida que las URL no se agregaban. Pero dejaré la pregunta: ¿Es esta la manera correcta de hacer esto?]
¿Puedo confiar en memory_get_usage()
de esta manera? ¿Hay mejores métodos alternativos para obtener el uso de la memoria (he visto algunos scripts analizar el resultado de los comandos del shell)?
Bueno, nunca tuve un problema de memoria con mis scripts PHP, así que no creo que pueda ser de mucha ayuda para encontrar la causa del problema, pero lo que puedo recomendar es que obtengas un acelerador de PHP, notarás un serio aumento en tu rendimiento y uso de memoria con disminución. Aquí hay una lista de aceleradores y un artículo que compara algunos de ellos (3 veces mejor rendimiento con cualquiera de ellos)
Los puntos de referencia tienen 2 años pero se tiene la idea de que el rendimiento aumenta.
Si es necesario, también puede aumentar su límite de memoria en PHP si todavía tiene problemas incluso con el acelerador. Abre tu php.ini y encuentra:
memory_limit = 32M;
y solo aumentarlo un poco.
También asumo que memory_get_usage()
es seguro pero supongo que puedes comparar ambos métodos y decidir por ti mismo, aquí hay una función que analiza las llamadas al sistema:
function Memory_Usage($decimals = 2)
{
$result = 0;
if (function_exists(''memory_get_usage''))
{
$result = memory_get_usage() / 1024;
}
else
{
if (function_exists(''exec''))
{
$output = array();
if (substr(strtoupper(PHP_OS), 0, 3) == ''WIN'')
{
exec(''tasklist /FI "PID eq '' . getmypid() . ''" /FO LIST'', $output);
$result = preg_replace(''/[/D]/'', '''', $output[5]);
}
else
{
exec(''ps -eo%mem,rss,pid | grep '' . getmypid(), $output);
$output = explode('' '', $output[0]);
$result = $output[1];
}
}
}
return number_format(intval($result) / 1024, $decimals, ''.'', '''');
}
Use xdebug , ya que fue recientemente (el 29 de enero) actualizado para incluir ahora información de perfiles de memoria. Realiza un seguimiento de las llamadas a función y la cantidad de memoria que consumen. Esto le permite obtener una visión muy intuitiva de su código y, como mínimo, lo orienta a tomar conciencia de los problemas.
La documentación es útil, pero esencialmente tú, instálala habilita el perfil xdebug.profiler_enable = 1
y da la salida xdebug.profiler_output_dir=/some/path
a una herramienta como qcachegrind para hacer el trabajo pesado, dejando que se vea visualmente.
real_usage
funciona de esta manera:
El administrador de memoria de Zend no usa el sistema malloc por cada bloque que necesita. En cambio, asigna un gran bloque de memoria del sistema (en incrementos de 256 K, se puede cambiar configurando la variable de entorno ZEND_MM_SEG_SIZE
) y lo administra internamente. Entonces, hay dos tipos de uso de memoria:
- Cuánta memoria extrajo el motor del sistema operativo ("uso real")
- ¿Cuánto de esta memoria realmente fue utilizada por la aplicación ("uso interno")?
Cualquiera de estos puede ser devuelto por memory_get_usage()
. Cuál es más útil para usted depende de lo que está buscando. Si está buscando optimizar su código en partes específicas, "interno" podría serle más útil. Si está rastreando el uso de la memoria globalmente, "real" sería de mayor utilidad. memory_limit
limita el número "real", por lo que tan pronto como todos los bloques que están permitidos por el límite se toman del sistema y el administrador de memoria no puede asignar un bloque solicitado, la asignación falla. Tenga en cuenta que el uso "interno" en este caso podría ser menor que el límite, pero la asignación aún podría fallar debido a la fragmentación.
Además, si está utilizando alguna herramienta de seguimiento de memoria externa, puede establecer esta variable de entorno USE_ZEND_ALLOC=0
que deshabilitaría el mecanismo anterior y hará que el motor siempre use malloc()
. Esto tendría un rendimiento mucho peor, pero le permite utilizar herramientas de seguimiento malloc.
Vea también un artículo sobre este administrador de memoria , también tiene algunos ejemplos de código.