La forma más sencilla de perfilar un script PHP

289

¿Cuál es la forma más fácil de perfilar un script PHP?

Me encantaría agregar algo que me muestre un volcado de todas las llamadas a funciones y cuánto tiempo tomaron, pero también estoy de acuerdo con poner algo alrededor de funciones específicas.

Intenté experimentar con la función microtime :

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);

pero eso a veces me da resultados negativos. Además, es muy problemático esparcirlo por todo mi código.

Mark Biek
fuente
77
Hola Mark, mira
Mina
16
Ese comentario vinculado por @Midiane no tiene sentido. Si pareció resolver el problema del comentarista, debe haber sido una coincidencia. Sólo mediante microtime()dará lugar a expresiones que evalúan a veces como: "0.00154800 1342892546" - "0.99905700 1342892545"que evaluará como: 0.001548 - 0.999057. Puede usar microtime( TRUE )para evitar ese problema, como lo señaló @luka.
JMM

Respuestas:

104

La extensión PECL APD se utiliza de la siguiente manera:

<?php
apd_set_pprof_trace();

//rest of the script
?>

Después, analiza el archivo generado usando pprofp.

Salida de ejemplo:

Trace for /home/dan/testapd.php
Total Elapsed Time = 0.00
Total System Time  = 0.00
Total User Time    = 0.00


Real         User        System             secs/    cumm
%Time (excl/cumm)  (excl/cumm)  (excl/cumm) Calls    call    s/call  Memory Usage Name
--------------------------------------------------------------------------------------
100.0 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0000   0.0009            0 main
56.9 0.00 0.00  0.00 0.00  0.00 0.00     1  0.0005   0.0005            0 apd_set_pprof_trace
28.0 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 preg_replace
14.3 0.00 0.00  0.00 0.00  0.00 0.00    10  0.0000   0.0000            0 str_replace

Advertencia: la última versión de APD tiene fecha de 2004, la extensión ya no se mantiene y tiene varios problemas de compatibilidad (ver comentarios).

Vincent
fuente
19
La extensión APD está rota en php 5.4.
Skynet
En respuesta al usuario 457015, pude hacer que funcione en un sitio web que ejecuta wordpress 3.8.1 y PHP 5.3.10 y parecía funcionar bien.
Supernovah
1
@Supernovah, user457015 dijo PHP 5.4. No dijo que estaba roto en PHP 5.3.
magnus
@ user1420752 Estoy ejecutando 5.3.27 y no funciona allí también. Me sale un error de función indefinido.
Fractaly
2
La última versión de APD es de 2004 (!) No funciona con PHP 7. Al intentar instalar para PHP 5 pecl install apd, aparece un mensaje de error sobre "config.m4". Parece que tienes que instalarlo desde el código fuente, que aún no he probado. En serio, ¿no existe una herramienta moderna y actualizada de creación de perfiles basada en CLI para PHP que se instale con Homebrew, requiera una configuración mínima y proporcione resultados fácilmente legibles para los humanos?
2016
267

Quieres xdebug , creo. Instálelo en el servidor, enciéndalo, bombee la salida a través de kcachegrind (para Linux) o wincachegrind (para Windows) y le mostrará algunos gráficos bonitos que detallan los tiempos exactos, los recuentos y el uso de la memoria (pero Necesito otra extensión para eso).

Se mece, en serio: D

mercutio
fuente
66
Encontré esto mucho más fácil de implementar que la solución APD. Pero tal vez sea porque, por alguna razón, APD no se compiló correctamente en mi sistema. También los gráficos de kcachegrind eran tan bonitos como se prometió.
wxs
1
@EvilPuppetMaster, necesita compilar php con --enable-memory-limit o usar una versión php más moderna. Ver xdebug.org/docs/basic#xdebug_memory_usage
mercutio
52
xdebug + webgrind se convirtió rápidamente en mi arma preferida para la creación de perfiles rápida y fácil. code.google.com/p/webgrind
xkcd150
66
xdebug + xdebug_start_trace () + xdebug_stop_trace () = win
quano
3
Fue muy fácil trabajar en Windows con XAMPP. Ya tenía netbeans configurado para xdebug. Lo único que debe hacer es cambiar la configuración de xdebug en php.ini a xdebug.profiler_output_name = "cachegrind.out.% T-% s" o de lo contrario no se generará ningún resultado. Requiere reiniciar apache.
principiante_
97

No se necesitan extensiones, solo use estas dos funciones para crear perfiles simples.

// Call this at each point of interest, passing a descriptive string
function prof_flag($str)
{
    global $prof_timing, $prof_names;
    $prof_timing[] = microtime(true);
    $prof_names[] = $str;
}

// Call this when you're done and want to see the results
function prof_print()
{
    global $prof_timing, $prof_names;
    $size = count($prof_timing);
    for($i=0;$i<$size - 1; $i++)
    {
        echo "<b>{$prof_names[$i]}</b><br>";
        echo sprintf("&nbsp;&nbsp;&nbsp;%f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}

Aquí hay un ejemplo, llamando a prof_flag () con una descripción en cada punto de control, y prof_print () al final:

prof_flag("Start");

   include '../lib/database.php';
   include '../lib/helper_func.php';

prof_flag("Connect to DB");

   connect_to_db();

prof_flag("Perform query");

   // Get all the data

   $select_query = "SELECT * FROM data_table";
   $result = mysql_query($select_query);

prof_flag("Retrieve data");

   $rows = array();
   $found_data=false;
   while($r = mysql_fetch_assoc($result))
   {
       $found_data=true;
       $rows[] = $r;
   }

prof_flag("Close DB");

   mysql_close();   //close database connection

prof_flag("Done");
prof_print();

La salida se ve así:

Iniciar
   0.004303
Conectarse a DB
   0.003518
Realizar consulta
   0.000308
Recuperar datos
   0.000009
Cerrar DB
   0.000049
Listo

TimH - Codidact
fuente
37

Publicación cruzada de mi referencia de SO Documentation beta que se desconecta.

Perfilado con XDebug

Una extensión para PHP llamada Xdebug está disponible para ayudar a perfilar aplicaciones PHP , así como a la depuración en tiempo de ejecución. Al ejecutar el generador de perfiles, la salida se escribe en un archivo en formato binario llamado "cachegrind". Las aplicaciones están disponibles en cada plataforma para analizar estos archivos. No se necesitan cambios en el código de la aplicación para realizar este perfil.

Para habilitar la creación de perfiles, instale la extensión y ajuste la configuración de php.ini. Algunas distribuciones de Linux vienen con paquetes estándar (por ejemplo, el php-xdebugpaquete de Ubuntu ). En nuestro ejemplo, ejecutaremos el perfil opcionalmente en función de un parámetro de solicitud. Esto nos permite mantener la configuración estática y activar el generador de perfiles solo cuando sea necesario.

# php.ini settings
# Set to 1 to turn it on for every request
xdebug.profiler_enable = 0
# Let's use a GET/POST parameter to turn on the profiler
xdebug.profiler_enable_trigger = 1
# The GET/POST value we will pass; empty for any value
xdebug.profiler_enable_trigger_value = ""
# Output cachegrind files to /tmp so our system cleans them up later
xdebug.profiler_output_dir = "/tmp"
xdebug.profiler_output_name = "cachegrind.out.%p"

A continuación, use un cliente web para realizar una solicitud a la URL de su aplicación que desea perfilar, p. Ej.

http://example.com/article/1?XDEBUG_PROFILE=1

A medida que la página se procesa, escribirá en un archivo con un nombre similar a

/tmp/cachegrind.out.12345

Por defecto, el número en el nombre del archivo es la identificación del proceso que lo escribió. Esto es configurable con la xdebug.profiler_output_nameconfiguración.

Tenga en cuenta que escribirá un archivo para cada solicitud / proceso PHP que se ejecute. Entonces, por ejemplo, si desea analizar una publicación de formulario, se escribirá un perfil para la solicitud GET para mostrar el formulario HTML. El parámetro XDEBUG_PROFILE deberá pasarse a la solicitud POST posterior para analizar la segunda solicitud que procesa el formulario. Por lo tanto, al crear perfiles, a veces es más fácil ejecutar curl para PUBLICAR un formulario directamente.

Analizando la salida

Una vez escrito, el caché del perfil puede ser leído por una aplicación como KCachegrind o Webgrind . PHPStorm, un popular IDE de PHP, también puede mostrar estos datos de perfil .

KCachegrind

KCachegrind, por ejemplo, mostrará información que incluye:

  • Funciones ejecutadas
  • Tiempo de llamada, tanto en sí mismo como inclusivo de llamadas de función posteriores
  • Número de veces que se llama a cada función
  • Gráficos de llamadas
  • Enlaces al código fuente

Qué buscar

Obviamente, el ajuste del rendimiento es muy específico para los casos de uso de cada aplicación. En general es bueno buscar:

  • Llamadas repetidas a la misma función que no esperaría ver. Para las funciones que procesan y consultan datos, estas podrían ser oportunidades principales para que su aplicación se almacene en caché.
  • Funciones de funcionamiento lento. ¿Dónde pasa la aplicación la mayor parte de su tiempo? La mejor recompensa en el ajuste del rendimiento se centra en aquellas partes de la aplicación que consumen la mayor parte del tiempo.

Nota : Xdebug, y en particular sus características de creación de perfiles, requieren muchos recursos y ralentizan la ejecución de PHP. Se recomienda no ejecutarlos en un entorno de servidor de producción.

Matt S
fuente
3
Agregando a la lista de herramientas para analizar el perfil de caché: PhpStorm también tiene una herramienta para la previsualización de la caché de perfil
peterchaula
1
@peter Olvidé que PHPStorm tiene esa característica. Lo agregué con un enlace a la documentación. ¡Gracias!
Matt S
¿Alguna forma de obtener un informe de texto (no GUI) directamente en el servidor?
Alexander Shcheblikin
1
@ Mark, ¿podría marcar esto como la respuesta, por favor? La respuesta actual estaba desactualizada incluso cuando se publicó y no ha funcionado durante muchos años. Esto funciona, y no conozco un método mejor.
Mawg dice que reinstale a Mónica el
24

Si restar microtimes le da resultados negativos, intente usar la función con el argumento true( microtime(true)). Contrue , la función devuelve un flotante en lugar de una cadena (como lo hace si se llama sin argumentos).

luka
fuente
24

Honestamente, voy a argumentar que usar NewRelic para perfilar es lo mejor.

Es una extensión PHP que no parece ralentizar el tiempo de ejecución y hacen el monitoreo por usted, lo que permite un desglose decente. En la versión cara, permiten un gran desglose (pero no podemos permitirnos su modelo de precios).

Aún así, incluso con el plan gratuito / estándar, es obvio y simple dónde se encuentra la mayor parte de la fruta. También me gusta que puede darte una idea sobre las interacciones de DB también.

captura de pantalla de una de las interfaces al perfilar

zeroasterisk
fuente
16
New Relic parece prometedor, claro. Sin embargo, la parte de "Divulgación de los datos de su aplicación" de su Política de privacidad me rechazó al instante. En mi humilde opinión, el intercambio de piezas de propiedad de código fuente con los terceros es un poco demasiado.
Cengiz puede
8
No saltando en su defensa aquí, pero parece que "Datos de la aplicación" es solo información de rendimiento e información de configuración del sistema, no el código fuente de su aplicación.
David Shields
Fir mi nueva reliquia muestra mi "WebTransaction" como el 99% del tiempo, y no tengo la cuenta profesional para "ApplicationTraces"
Karthik T
1
intente registrarse en: newrelic.com/rackspace <debería darle "estándar" gratis
zeroasterisk
15

Perfil del pobre hombre, no se requieren extensiones. Admite perfiles anidados y porcentaje del total:

function p_open($flag) {
    global $p_times;
    if (null === $p_times)
        $p_times = [];
    if (! array_key_exists($flag, $p_times))
        $p_times[$flag] = [ 'total' => 0, 'open' => 0 ];
    $p_times[$flag]['open'] = microtime(true);
}

function p_close($flag)
{
    global $p_times;
    if (isset($p_times[$flag]['open'])) {
        $p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']);
        unset($p_times[$flag]['open']);
    }
}

function p_dump()
{
    global $p_times;
    $dump = [];
    $sum  = 0;
    foreach ($p_times as $flag => $info) {
        $dump[$flag]['elapsed'] = $info['total'];
        $sum += $info['total'];
    }
    foreach ($dump as $flag => $info) {
        $dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum;
    }
    return $dump;
}

Ejemplo:

<?php

p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');

var_dump(p_dump());

Rendimientos:

array:3 [
  "foo" => array:2 [
    "elapsed" => 9.000766992569
    "percent" => 0.4736904954747
  ]
  "bar" => array:2 [
    "elapsed" => 7.0004580020905
    "percent" => 0.36841864946596
  ]
  "baz" => array:2 [
    "elapsed" => 3.0001420974731
    "percent" => 0.15789085505934
  ]
]
obispo
fuente
13

PECL XHPROF también parece interesante. Tiene una interfaz HTML en la que se puede hacer clic para ver informes y documentación bastante sencilla . Sin embargo, todavía tengo que probarlo.

Josef Sábl
fuente
Parece que no está recibiendo mucho amor. Última actualización en 2009, no hay paquetes PEAR para 5.3, 5.4 y posteriores ...
2013
1
Facebook creó una bifurcación con soporte a través de php 5.5 github.com/facebook/xhprof
borkencode
Consulte también este tenedor que propone algunos ajustes adicionales: github.com/preinheimer/xhprof
Fedir RYKHTIK
xhprof.io proporciona GUI para los datos recopilados con XHProf, así como la capacidad de almacenar datos en la base de datos con fines de análisis histórico. Soy el autor de esta última implementación.
Gajus
10

Me gusta usar phpDebug para perfilar. http://phpdebug.sourceforge.net/www/index.html

Produce todo el uso de tiempo / memoria para cualquier SQL utilizado, así como todos los archivos incluidos. Obviamente, funciona mejor en código que se abstrae.

Para el perfil de funciones y clases solo usaré microtime()+ get_memory_usage()+ get_peak_memory_usage().

Eric Lamb
fuente
6

Para la evaluación comparativa, como en su ejemplo, utilizo el paquete de referencia de pera . Estableces marcadores para medir. La clase también proporciona algunos asistentes de presentación, o puede procesar los datos como mejor le parezca.

De hecho, lo tengo envuelto en otra clase con un método __destruct. Cuando sale un script, la salida se registra a través de log4php en syslog, por lo que tengo muchos datos de rendimiento para trabajar.

Gary Richardson
fuente
3

XDebug no es estable y no siempre está disponible para una versión particular de php. Por ejemplo, en algunos servidores todavía ejecuto php-5.1.6, es lo que viene con RedHat RHEL5 (y por cierto aún recibe actualizaciones para todos los problemas importantes), y el reciente XDebug ni siquiera compila con este php. Así que terminé cambiando al depurador DBG. Su evaluación comparativa php proporciona el tiempo para funciones, métodos, módulos e incluso líneas.

usuario2221743
fuente
2

Todos ustedes definitivamente deberían revisar este nuevo perfilador de php.

https://github.com/NoiseByNorthwest/php-spx

Redefine la forma en que php profilers recopila y presenta el resultado. En lugar de generar solo un número total de llamadas a funciones particulares y el tiempo total empleado en ejecutarlo, PHP-SPX presenta toda la línea de tiempo de ejecución de la solicitud de una manera perfectamente legible. A continuación se muestra la pantalla de GUI que proporciona.

ingrese la descripción de la imagen aquí

Jacek Dziurdzikowski
fuente