¿Cómo puedo medir la velocidad del código escrito en PHP? [cerrado]

Respuestas:

195

Tienes (al menos) dos soluciones:

El bastante "ingenuo" está usando microtime (verdadero) antes y después de una porción de código, para saber cuánto tiempo ha pasado durante su ejecución; otras respuestas dijeron eso y ya dieron ejemplos, así que no diré mucho más.

Esta es una buena solución si desea comparar un par de instrucciones; como comparar dos tipos de funciones, por ejemplo: es mejor si se hace miles de veces, para asegurarse de que se promedie cualquier "elemento perturbador".

Algo como esto, entonces, si desea saber cuánto tiempo lleva serializar una matriz:

$before = microtime(true);

for ($i=0 ; $i<100000 ; $i++) {
    serialize($list);
}

$after = microtime(true);
echo ($after-$before)/$i . " sec/serialize\n";

No es perfecto, pero es útil y no lleva mucho tiempo configurarlo.



La otra solución, que funciona bastante bien si desea identificar qué función lleva mucho tiempo en un script completo, es usar:

  • La extensión Xdebug , para generar datos de perfiles para el script
  • Software que lee los datos de creación de perfiles y le presenta algo legible. Conozco tres de esos:
    • Webgrind ; interfaz web ; debería funcionar en cualquier servidor Apache + PHP
    • WinCacheGrind ; solo en windows
    • KCacheGrind ; probablemente solo Linux y similar a Linux; Ese es el que prefiero, por cierto

Para obtener archivos de creación de perfiles, debe instalar y configurar Xdebug; eche un vistazo a la página de creación de perfiles de scripts PHP de la documentación.

Lo que generalmente hago no es habilitar el generador de perfiles de forma predeterminada (genera archivos bastante grandes y ralentiza las cosas) , sino que uso la posibilidad de enviar un parámetro llamado XDEBUG_PROFILEdatos GET, para activar el perfil solo para la página que necesito.
La parte relacionada con la creación de perfiles de mi php.ini se ve así:

xdebug.profiler_enable = 0              ; Profiling not activated by default
xdebug.profiler_enable_trigger = 1      ; Profiling activated when requested by the GET parameter
xdebug.profiler_output_dir = /tmp/ouput_directory
xdebug.profiler_output_name = files_names

(Lea la documentación para más información)

Esta captura de pantalla es de un programa C ++ en KcacheGrind: (fuente: sourceforge.net ) Obtendrá exactamente el mismo tipo de cosas con scripts PHP ;-) (Con KCacheGrind, quiero decir; WinCacheGrind no es tan bueno como KCacheGrind ... )http://kcachegrind.sourceforge.net/html/pics/KcgShot3Large.gif



Esto le permite obtener una buena vista de lo que lleva tiempo en su aplicación y, a veces, definitivamente ayuda a localizar la función que está ralentizando todo ^^

Tenga en cuenta que Xdebug cuenta el tiempo de CPU empleado por PHP; cuando PHP está esperando una respuesta de una base de datos (por ejemplo), no está funcionando; solo esperando. ¡Entonces Xdebug pensará que la solicitud DB no lleva mucho tiempo!
Esto debe perfilarse en el servidor SQL, no PHP, así que ...


Espero que esto sea útil :-) ¡
Diviértete!

Pascal MARTIN
fuente
1
Existe una compilación de Windows de QCacheGrind :-) sourceforge.net/projects/qcachegrindwin
François Breton
43

Para cosas rápidas, hago esto (en PHP):

$startTime = microtime(true);
doTask(); // whatever you want to time
echo "Time:  " . number_format(( microtime(true) - $startTime), 4) . " Seconds\n";

También puede utilizar un generador de perfiles como http://xdebug.org/ .

Scott Saunders
fuente
2
Para mayor precisión, sugeriría (a) usar un bucle y promediar el tiempo y (b) usar archivos separados para cada cosa que esté probando. Si tiene varios tiempos dentro de un script, su orden puede marcar la diferencia a veces.
DisgruntledGoat
9

Hice una clase de cronometraje simple, tal vez sea útil para alguien:

class TimingHelper {

    private $start;

    public function __construct() {
        $this->start = microtime(true);
    }

    public function start() {
        $this->start = microtime(true);
    }

    public function segs() {
        return microtime(true) - $this->start;
    }

    public function time() {
        $segs = $this->segs();
        $days = floor($segs / 86400);
        $segs -= $days * 86400;
        $hours = floor($segs / 3600);
        $segs -= $hours * 3600;
        $mins = floor($segs / 60);
        $segs -= $mins * 60;
        $microsegs = ($segs - floor($segs)) * 1000;
        $segs = floor($segs);

        return 
            (empty($days) ? "" : $days . "d ") . 
            (empty($hours) ? "" : $hours . "h ") . 
            (empty($mins) ? "" : $mins . "m ") . 
            $segs . "s " .
            $microsegs . "ms";
    }

}

Utilizar:

$th = new TimingHelper();
<..code being mesured..>
echo $th->time();
$th->start(); // if it's the case
<..code being mesured..>
echo $th->time();

// result: 4d 17h 34m 57s 0.00095367431640625ms 
Nelson Teixeira
fuente
Escribiste mal: es echo, no$echo
SuN
9

Actualización 2020

Han pasado muchos años desde la última vez que respondí a estas preguntas, así que pensé que esto merece una actualización sobre el panorama de APM.

  • Cisco compró AppDynamics y la cuenta gratuita para siempre que solían ofrecer se ha retirado de su sitio web.
  • NewRelic ha bajado su precio de $ 149 / mes / anfitrión a $ 25 / mes / anfitrión para competir con el recién llegado al mercado de APM, Datadog, que ofrece $ 31 / mes / anfitrión.
  • Las características de Datadog APM siguen siendo ligeras y dejan mucho que desear. Sin embargo, los veo mejorando y mejorando estos durante el próximo año.
  • Ruxit ha sido comprado por Dynatrace. No es sorprendente aquí ya que Ruxit fue construido por ex empleados de Dynatrace. Esto permitió que Dynatrace se transformara en un modelo verdaderamente SaaS para mejorar. Diga adiós a ese voluminoso cliente Java si lo desea.
  • Ahora también hay opciones gratuitas / de código abierto. Pedido Apache Skywalking que es muy popular en China entre sus principales compañías de tecnología y PinPoint que ofrece una demostración que puede probar antes de la instalación. Ambos requieren que administres el alojamiento, así que prepárate para poner en marcha algunas máquinas virtuales y dedica un tiempo a la instalación y configuración.
  • No he probado ninguna de estas soluciones APM de código abierto, por lo que no estoy en condiciones de recomendarlas; sin embargo, he gestionado personalmente la implementación de todas estas soluciones APM para varias organizaciones, ya sea en las instalaciones o en la nube para cientos de aplicaciones / microservicios. Así que puedo decir con confianza que no puede equivocarse con ninguno de los proveedores si se ajustan a sus necesidades.


Respondido originalmente en octubre de 2015

Aquí hay una respuesta directa a su pregunta.

¿Existe un software para medir eso?

Sí hay. Me pregunto por qué nadie lo ha mencionado todavía. Aunque las respuestas sugeridas anteriormente parecen estar bien para una verificación rápida, no son escalables a largo plazo o para un proyecto más grande.

¿Por qué no utilizar una herramienta de supervisión del rendimiento de las aplicaciones (APM) que está diseñada exactamente para eso y mucho más? Consulte NewRelic, AppDynamics, Ruxit (todos tienen versión gratuita) para monitorear el tiempo de ejecución, el uso de recursos y el rendimiento de cada aplicación al nivel del método.

na-98
fuente
6

Si desea probar rápidamente el rendimiento de un marco, puede colocar el archivo index.php

//at beginning
$milliseconds = round(microtime(true) * 1000);

//and at the end
echo round(microtime(true) * 1000) - $milliseconds;

Cada vez obtendrá el tiempo de ejecución en milisegundos . Porque los microsegundos no son demasiado útiles para probar un caso marco.

tasmaniski
fuente
4

Me gustaría compartir con ustedes una función hecha por mí mismo que uso para medir la velocidad de cualquier función existente hasta 10 argumentos:

function fdump($f_name='', $f_args=array()){

    $f_dump=array();
    $f_result='';

    $f_success=false;

    $f_start=microtime();
    $f_start=explode(' ', $f_start);
    $f_start=$f_start[1] + $f_start[0];

    if(function_exists($f_name)){

        if(isset($f_args[0])&&is_array($f_args[0])){
            if($f_result=$f_name($f_args)){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[1])){
            if($f_result=$f_name($f_args[0])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[2])){
            if($f_result=$f_name($f_args[0],$f_args[1])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[3])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[4])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[5])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[6])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[7])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[8])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[9])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8])){
                $f_success=true;
            }
        }
        elseif(!isset($f_args[10])){
            if($f_result=$f_name($f_args[0],$f_args[1],$f_args[2],$f_args[3],$f_args[4],$f_args[5],$f_args[6],$f_args[7],$f_args[8],$f_args[9])){
                $f_success=true;
            }
        }
    }
    $f_end=microtime();
    $f_end=explode(' ', $f_end);
    $f_end=$f_end[1] + $f_end[0];

    $f_time=round(($f_end - $f_start), 4);
    $f_dump['f_success']=$f_success;
    $f_dump['f_time']=$f_time;
    $f_dump['f_result']=$f_result;

    var_dump($f_dump);exit;

    //return $f_result;

}

Ejemplo

function do_stuff($arg1='', $arg2=''){
    return $arg1.' '.$arg2;
}

fdump('do_stuff',array('hello', 'world'));

Devoluciones

  array(3) {
    ["f_success"]=>
    bool(true)
    ["f_time"]=>
    float(0)            //too fast...
    ["f_result"]=>
    string(11) "hello world"
  }
RafaSashi
fuente
3

Si es algo que se puede probar fuera del contexto web, solo uso el timecomando Unix .

caos
fuente
3

Zend Studio ha incorporado soporte para la creación de perfiles utilizando XDebug o ZendDebugger. Perfilará su código, indicándole exactamente cuánto tiempo tomó cada función. Es una herramienta fantástica para averiguar dónde están sus cuellos de botella.

OverloadUT
fuente
1

Puede usar cosas básicas como almacenar marcas de tiempo o microtime () antes y después de una operación para calcular el tiempo necesario. Eso es fácil de hacer, pero no muy preciso. Tal vez una mejor solución sea Xdebug , nunca he trabajado con él, pero parece ser el depurador / perfilador de PHP más conocido que puedo encontrar.

Alex
fuente