Forma precisa de medir los tiempos de ejecución de scripts php

270

Quiero saber cuántos milisegundos tarda un PHP for-loop en ejecutarse.

Conozco la estructura de un algoritmo genérico, pero no tengo idea de cómo implementarlo en PHP:

Begin
init1 = timer(); // where timer() is the amount of milliseconds from midnight
the loop begin
some code
the loop end
total = timer() - init1;
End
DomingoSL
fuente
Puede jugar con franjas de declaraciones microtime () si necesita esto en producción, pero si es solo para probar, solo use el perfilador de xdebug, por ejemplo. Ningún código desordenado es una verdadera ventaja.
Escrito el

Respuestas:

525

Puede usar la microtimefunción para esto. De la documentación :

microtime - Devuelve la marca de tiempo actual de Unix con microsegundos


Si get_as_floatse establece en TRUE, entonces microtime()devuelve un flotante, que representa el tiempo actual en segundos desde la época de Unix con precisión al microsegundo más cercano.

Ejemplo de uso:

$start = microtime(true);
while (...) {

}
$time_elapsed_secs = microtime(true) - $start;
Tim Cooper
fuente
36
Necesitas microtime(true)si quieres hacer cálculos con el valor de retorno.
solitario el
77
Sé que esto es muuuuucho tarde (casi 4 años), pero como comentario ... el uso de estos cálculos (con el parámetro get_as_floatas true) le dará resultados en segundos , según la documentación de PHP.
Alejandro Iván
66
@patrick y eso es lo que dije: si get_as_floates así true, microtime()devuelve el valor que representa los segundos ...
Alejandro Iván
2
Si bien esta es una publicación muy antigua, debemos referirnos al hecho de que el flotador devuelto contiene los microsegundos ... La mejor solución es multiplicarlo por 1000 ... vea stackoverflow.com/questions/3656713/… como ejemplo. .
enojado 84
1
Esta respuesta está desactualizada. Hoy en día, la mejor manera de informar el tiempo de ejecución del script es una sola línea al final de su código: $time = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"]; (Más información en una respuesta a continuación .)
ashleedawg
84

Se puede usar microtime(true)con los siguientes modales:

Ponga esto al comienzo de su archivo php:

//place this before any script you want to calculate time
$time_start = microtime(true);

// su código de script va aquí

// do something

Pon esto al final de tu archivo php:

// Display Script End time
$time_end = microtime(true);

//dividing with 60 will give the execution time in minutes other wise seconds
$execution_time = ($time_end - $time_start)/60;

//execution time of the script
echo '<b>Total Execution Time:</b> '.$execution_time.' Mins';

Producirá el resultado minutes.

Aditya P Bhatt
fuente
72

Puede usar REQUEST_TIMEdesde la $_SERVERmatriz superglobal. De la documentación :

REQUEST_TIME
La marca de tiempo del inicio de la solicitud. (Disponible desde PHP 5.1.0.)

REQUEST_TIME_FLOAT
La marca de tiempo del inicio de la solicitud, con precisión de microsegundos . (Disponible desde PHP 5.4.0.)

De esta manera, no necesita guardar una marca de tiempo al comienzo de su secuencia de comandos. Simplemente puedes hacer:

<?php
// Do stuff
usleep(mt_rand(100, 10000));

// At the end of your script
$time = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];

echo "Did stuff in $time seconds\n";
?>

Aquí, $timecontendría el tiempo transcurrido desde el inicio de la secuencia de comandos en segundos, con precisión de microsegundos (por ejemplo, 1.341durante 1 segundo y 341 microsegundos)


Más información:

Documentación de PHP : $_SERVERvariables y microtimefunción

Iwazaru
fuente
Esto es útil para saber. Para que pueda utilizar:$start = $_SERVER["REQUEST_TIME_FLOAT"]; $myscript = microtime(true); $bootstrap = $myscript - $start; ...do stuff ...; $myscripttime = microtime(true) - $myscript;
pspahn
1
Bueno, sobre todo el uso de esto es que podría hacer: $myscripttime = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];al final de su secuencia de comandos sin tener que guardar una marca de tiempo al principio.
Iwazaru
1
Según la documentación vinculada, $timecontendrá la diferencia en segundos , no en microsegundos .
Wim Deblauwe
44
@WimDeblauwe Para aclarar, sí, el resultado es en segundos. Pero con precisión de microsegundos . Por ejemplo, 1.1equivale a 1 segundo + 100 microsegundos.
Chris Harrison
1
Esta es la mejor manera de medir el tiempo de respuesta
Mike Aron
27

Crear archivo loadtime.php

<?php
class loadTime{
    private $time_start     =   0;
    private $time_end       =   0;
    private $time           =   0;
    public function __construct(){
        $this->time_start= microtime(true);
    }
    public function __destruct(){
        $this->time_end = microtime(true);
        $this->time = $this->time_end - $this->time_start;
        echo "Loaded in $this->time seconds\n";
    }
}

Que en el comienzo de su guión, después de <?phpescribirinclude 'loadtime.php'; $loadtime=new loadTime();

Cuando la página se carga al final, se escribirá "Cargado en x segundos"

Solo Omsarashvili
fuente
55
¡Ordenado! Pero si no destruye explícitamente su objeto, la salida aparecerá después de la </html>etiqueta de cierre que no es válida
Dmitry Pashkevich
@gondo No, serán segundos (con microsegundos expresados ​​como valores decimales de sceconds)
FrancescoMM
19
$start = microtime(true);
for ($i = 0; $i < 10000; ++$i) {
    // do something
}
$total = microtime(true) - $start;
echo $total;
Dvir Azulay
fuente
7

Aquí hay una función que multiplica la ejecución de cualquier pieza de código PHP, al igual que lo hace el módulo timeit de Python: https://gist.github.com/flaviovs/35aab0e85852e548a60a

Cómo usarlo:

include('timeit.php');
const SOME_CODE = '
        strlen("foo bar");
';
$t = timeit(SOME_CODE);
print "$t[0] loops; $t[2] per loop\n";

Resultado:

$ php x.php 
100000 loops; 18.08us per loop

Descargo de responsabilidad: soy el autor de este Gist

EDITAR: timeit ahora es un proyecto independiente y autónomo en https://github.com/flaviovs/timeit

flaviovs
fuente
5

Tiene la idea correcta, excepto que está disponible una sincronización más precisa con la función microtime () .

Si lo que está dentro del bucle es rápido, es posible que el tiempo transcurrido aparente sea cero. Si es así, envuelva otro bucle alrededor del código y llámelo repetidamente. Asegúrese de dividir la diferencia entre el número de iteraciones para obtener una vez por vez. He perfilado un código que requería 10,000,000 iteraciones para obtener resultados de tiempo consistentes y confiables.

wallyk
fuente
3

Pensé en compartir la función que armé. Esperemos que pueda ahorrarle tiempo.

Originalmente se usó para rastrear el tiempo de un script basado en texto, por lo que la salida está en forma de texto. Pero puede modificarlo fácilmente a HTML si lo prefiere.

Hará todos los cálculos por usted durante cuánto tiempo ha pasado desde el inicio del guión y en cada paso. Formatea toda la salida con 3 decimales de precisión. (Abajo a milisegundos)

Una vez que lo copie en la parte superior de su secuencia de comandos, todo lo que debe hacer es colocar las llamadas a la función recordTime después de cada pieza que desee cronometrar.

Copie esto en la parte superior de su archivo de script:

$tRecordStart = microtime(true);
header("Content-Type: text/plain");
recordTime("Start");

function recordTime ($sName) {
  global $tRecordStart;
  static $tStartQ;
  $tS = microtime(true);
  $tElapsedSecs = $tS - $tRecordStart;
  $tElapsedSecsQ = $tS - $tStartQ;
  $sElapsedSecs = str_pad(number_format($tElapsedSecs, 3), 10, " ", STR_PAD_LEFT);
  $sElapsedSecsQ = number_format($tElapsedSecsQ, 3);
  echo "//".$sElapsedSecs." - ".$sName;
  if (!empty($tStartQ)) echo " In ".$sElapsedSecsQ."s";
  echo "\n";
  $tStartQ = $tS;
}

Para rastrear el tiempo que pasa, solo haz:

recordTime("What We Just Did")

Por ejemplo:

recordTime("Something Else")
//Do really long operation.
recordTime("Really Long Operation")
//Do a short operation.
recordTime("A Short Operation")
//In a while loop.
for ($i = 0; $i < 300; $i ++) {
  recordTime("Loop Cycle ".$i)
}

Da resultados como este:

//     0.000 - Start
//     0.001 - Something Else In 0.001s
//    10.779 - Really Long Operation In 10.778s
//    11.986 - A Short Operation In 1.207s
//    11.987 - Loop Cycle 0 In 0.001s
//    11.987 - Loop Cycle 1 In 0.000s
...
//    12.007 - Loop Cycle 299 In 0.000s

¡Espero que esto ayude a alguien!

azoundria
fuente
2

Aquí hay un método muy simple y breve

<?php
$time_start = microtime(true);
//the loop begin
//some code
//the loop end
$time_end = microtime(true);
$total_time = $time_end - $time_start;
echo $total_time; // or whatever u want to do with the time
?>
Deepak Kumar
fuente
Creo que te falta algo Probé ese código cuando publiqué la respuesta
Deepak Kumar
var_dump (microtime (verdadero)); // float (1283846202.89) eso es lo que cuando usas microtime true
Deepak Kumar
También puede usar flotador en tiempo total
Deepak Kumar
2

si desea mostrar ese tiempo en segundos:

<?php
class debugTimer 
{
    private $startTime;
    private $callsCounter;

    function __construct() 
    {
        $this->startTime = microtime(true);
        $this->callsCounter = 0;
    }

    public function getTimer(): float
    {
        $timeEnd = microtime(true);
        $time = $timeEnd - $this->startTime;
        $this->callsCounter++;
        return $time;
    }

    public function getCallsNumer(): int
    {
        return $this->callsCounter;
    }
}

$timer = new debugTimer();
usleep(100);
echo '<br />\n
'.$timer->getTimer(). ' seconds before call #'.$timer->getCallsNumer();

usleep(100);
echo '<br />\n
'.$timer->getTimer(). ' seconds before call #'.$timer->getCallsNumer();
Eugene Kaurov
fuente
1

Aquí hay una implementación que devuelve segundos fraccionarios (es decir, 1.321 segundos)

/**
 * MICROSECOND STOPWATCH FOR PHP
 *
 * Class FnxStopwatch
 */
class FnxStopwatch
{
    /** @var float */
    private $start,
            $stop;

    public function start()
    {
        $this->start = self::microtime_float();
    }
    public function stop()
    {
        $this->stop = self::microtime_float();
    }
    public function getIntervalSeconds() : float
    {
        // NOT STARTED
        if (empty($this->start))
            return 0;
        // NOT STOPPED
        if (empty($this->stop))
            return ($this->stop - self::microtime_float());

        return $interval = $this->stop - $this->start;
    }

    /**
     * FOR MORE INFO SEE http://us.php.net/microtime
     *
     * @return float
     */
    private static function microtime_float() : float
    {
        list($usec, $sec) = explode(" ", microtime());

        return ((float)$usec + (float)$sec);
    }
}
mils
fuente
1

Aquí está mi script para medir el tiempo promedio

<?php

$times = [];
$nbrOfLoops = 4;
for ($i = 0; $i < $nbrOfLoops; ++$i) {
    $start = microtime(true);
    sleep(1);
    $times[] = microtime(true) - $start;
}

echo 'Average: ' . (array_sum($times) / count($times)) . 'seconds';
William Desportes
fuente
0

Puede encontrar el tiempo de ejecución en segundo con una sola función.

// ampersand is important thing here
function microSec( & $ms ) {
    if (\floatval( $ms ) == 0) {
        $ms = microtime( true );
    }
    else {
        $originalMs = $ms;
        $ms = 0;
        return microtime( true ) - $originalMs;
    }
}

// you don't have to define $ms variable. just function needs
// it to calculate the difference.
microSec($ms);
sleep(10);
echo microSec($ms) . " seconds"; // 10 seconds

for( $i = 0; $i < 10; $i++) {
    // you can use same variable everytime without assign a value
    microSec($ms);
    sleep(1);
    echo microSec($ms) . " seconds"; // 1 second
}

for( $i = 0; $i < 10; $i++) {
    // also you can use temp or useless variables
    microSec($xyzabc);
    sleep(1);
    echo microSec($xyzabc) . " seconds"; // 1 second
}
kodmanyagha
fuente