2009-02-11 41 views
204

PHP debe hacer un seguimiento de la cantidad de tiempo de CPU que un script en particular ha utilizado para imponer el límite de max_execution_time.Seguimiento del tiempo de ejecución del script en PHP

¿Hay alguna forma de acceder a esto dentro del script? Me gustaría incluir algunos registros con mis pruebas sobre cuánto CPU se quemó en el PHP real (el tiempo no se incrementa cuando el script está en espera y esperando la base de datos).

Estoy usando una caja de Linux.

Respuesta

156

En los sistemas unixoid (y en PHP 7.0.0 en Windows también), puede utilizar getrusage, como:

// Script start 
$rustart = getrusage(); 

// Code ... 

// Script end 
function rutime($ru, $rus, $index) { 
    return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000)) 
    - ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000)); 
} 

$ru = getrusage(); 
echo "This process used " . rutime($ru, $rustart, "utime") . 
    " ms for its computations\n"; 
echo "It spent " . rutime($ru, $rustart, "stime") . 
    " ms in system calls\n"; 

Tenga en cuenta que no lo hace necesita calcular una diferencia si está generando una instancia de PHP para cada prueba.

+0

caso de que el valor al final ser restado del valor al comienzo de la secuencia de comandos? Obtendré algunos números realmente extraños si no lo hago. Al igual que una página que tardó 0.05 segundos en generar dice que tomó 6 segundos de tiempo de CPU ... ¿es correcto? Vea aquí: http://blog.rompe.org/node/85 –

+0

@Darryl Hein: Ah, y obtiene resultados extraños porque está utilizando la concatenación de cadenas en lugar de la suma;) – phihag

+8

Dado que * .tv_usec está en microsegundos (1,000,000 por segundo) y * .tv_sec está en segundos, ¿no necesita multiplicar por 1000000 (o 1e6) en lugar de 1000? –

8

La forma más económica y sucia de hacerlo es simplemente realizar llamadas a microtime() en los lugares del código que desee comparar. Hágalo justo antes y después de las consultas a la base de datos y es simple eliminar esas duraciones del resto del tiempo de ejecución de su script.

Sugerencia: el tiempo de ejecución de PHP rara vez va a ser lo que hace que el script agote el tiempo de espera. Si un script expira, casi siempre va a ser una llamada a un recurso externo.

PHP documentación microtime: http://us.php.net/microtime

8

Creo que deberías mirar a xdebug. Las opciones de creación de perfiles le darán una ventaja para conocer muchos elementos relacionados con el proceso.

http://www.xdebug.org/

+0

Solo asegúrese de no instalar xdebug en un servidor de producción con muchos sitios web. Produce una enorme cantidad de registros y puede abrumar a un pequeño disco SSD. – Corgalore

361

Si todo lo que necesita es el tiempo del reloj de pared, más que el tiempo de ejecución de la CPU, entonces es fácil de calcular:

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

//sample script 
for($i=0; $i<1000; $i++){ 
//do anything 
} 

$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'; 
// in you get wierd result, use number_format((float) $execution_time, 10) 

Tenga en cuenta que esto incluye el tiempo que PHP es estaba esperando recursos externos, como discos o bases de datos, que no se usa para max_execution_time.

+29

Hola - esto rastrea el 'tiempo de reloj de pared' - no el tiempo de CPU. – twk

+6

Perfecto, estaba buscando una solución de seguimiento de tiempo de wallclock. – samiles

11

Gringod en developerfusion.com da esta buena respuesta:

<!-- put this at the top of the page --> 
<?php 
    $mtime = microtime(); 
    $mtime = explode(" ",$mtime); 
    $mtime = $mtime[1] + $mtime[0]; 
    $starttime = $mtime; 
;?> 

<!-- put other code and html in here --> 


<!-- put this code at the bottom of the page --> 
<?php 
    $mtime = microtime(); 
    $mtime = explode(" ",$mtime); 
    $mtime = $mtime[1] + $mtime[0]; 
    $endtime = $mtime; 
    $totaltime = ($endtime - $starttime); 
    echo "This page was created in ".$totaltime." seconds"; 
;?> 

De (http://www.developerfusion.com/code/2058/determine-execution-time-in-php/)

27
<?php 
// Randomize sleeping time 
usleep(mt_rand(100, 10000)); 

// As of PHP 5.4.0, REQUEST_TIME_FLOAT is available in the $_SERVER superglobal array. 
// It contains the timestamp of the start of the request with microsecond precision. 
$time = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"]; 

echo "Did nothing in $time seconds\n"; 
?> 
+0

No obtuve el resultado en segundos –

+0

Debe utilizar PHP 5.4.0 – Joyal

70

Shorter versión de la respuesta de talal7860

<?php 
// At start of script 
$time_start = microtime(true); 

// Anywhere else in the script 
echo 'Total execution time in seconds: ' . (microtime(true) - $time_start); 

Como se ha señalado, esto es 'hora de reloj de pared' no 'hora de CPU'

16

creé una clase ExecutionTime de respuesta phihag que se puede utilizar fuera de la caja:

class ExecutionTime 
{ 
    private $startTime; 
    private $endTime; 

    public function Start(){ 
     $this->startTime = getrusage(); 
    } 

    public function End(){ 
     $this->endTime = getrusage(); 
    } 

    private function runTime($ru, $rus, $index) { 
     return ($ru["ru_$index.tv_sec"]*1000 + intval($ru["ru_$index.tv_usec"]/1000)) 
    - ($rus["ru_$index.tv_sec"]*1000 + intval($rus["ru_$index.tv_usec"]/1000)); 
    }  

    public function __toString(){ 
     return "This process used " . $this->runTime($this->endTime, $this->startTime, "utime") . 
     " ms for its computations\nIt spent " . $this->runTime($this->endTime, $this->startTime, "stime") . 
     " ms in system calls\n"; 
    } 
} 

uso:

$executionTime = new ExecutionTime(); 
$executionTime->Start(); 
// code 
$executionTime->End(); 
echo $executionTime; 

Nota: La función getrusage sólo funciona en sistemas unixoid, y en php 7.0.0 en Windows.

+0

Nota: en Windows 'getrusage' solo funciona desde PHP 7. –

+0

@MartinvanDriel Anexé la nota. Gracias – Hamid

59

La forma más sencilla:

<?php 

$time1 = microtime(true); 

//script code 
//... 

$time2 = microtime(true); 
echo 'script execution time: ' . ($time2 - $time1); //value in seconds 
1

Es posible que sólo quieren saber el tiempo de ejecución de partes de su guión. La forma más flexible de medir partes o una secuencia de comandos completa es crear 3 funciones simples (código de procedimiento dado aquí pero podrías convertirlo en una clase poniendo el temporizador de clase {} a su alrededor y haciendo un par de ajustes). Este código funciona, simplemente copie y pegue y ejecute:

$tstart = 0; 
$tend = 0; 

function timer_starts() 
{ 
global $tstart; 

$tstart=microtime(true); ; 

} 

function timer_ends() 
{ 
global $tend; 

$tend=microtime(true); ; 

} 

function timer_calc() 
{ 
global $tstart,$tend; 

return (round($tend - $tstart,2)); 
} 

timer_starts(); 
file_get_contents('http://google.com'); 
timer_ends(); 
print('It took '.timer_calc().' seconds to retrieve the google page'); 
1

Escribí una función que comprueba el tiempo de ejecución restante.

Advertencia: El tiempo de ejecución del recuento es diferente en Windows y en la plataforma Linux.

/** 
* Check if more that `$miliseconds` ms remains 
* to error `PHP Fatal error: Maximum execution time exceeded` 
* 
* @param int $miliseconds 
* @return bool 
*/ 
function isRemainingMaxExecutionTimeBiggerThan($miliseconds = 5000) { 
    $max_execution_time = ini_get('max_execution_time'); 
    if ($max_execution_time === 0) { 
     // No script time limitation 
     return true; 
    } 
    if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 
     // On Windows: The real time is measured. 
     $spendMiliseconds = (microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"]) * 1000; 
    } else { 
     // On Linux: Any time spent on activity that happens outside the execution 
     //   of the script such as system calls using system(), stream operations 
     //   database queries, etc. is not included. 
     //   @see http://php.net/manual/en/function.set-time-limit.php 
     $resourceUsages = getrusage(); 
     $spendMiliseconds = $resourceUsages['ru_utime.tv_sec'] * 1000 + $resourceUsages['ru_utime.tv_usec']/1000; 
    } 
    $remainingMiliseconds = $max_execution_time * 1000 - $spendMiliseconds; 
    return ($remainingMiliseconds >= $miliseconds); 
} 

Usando:

while (true) { 
    // so something 

    if (!isRemainingMaxExecutionTimeBiggerThan(5000)) { 
     // Time to die. 
     // Safely close DB and done the iteration. 
    } 
} 
6
<?php 
    $time1 = microtime(true); 
     //script code 
     //...for or if or any thing you want to know! 
    $time2 = microtime(true); 
    echo 'Total execution time: ' . ($time2 - $time1);//value in seconds 
?> 
1

que va a ser más bonita si formatea la salida segundos como:

echo "Process took ". number_format(microtime(true) - $start, 2). " seconds."; 

imprimirá

Process took 6.45 seconds. 

Esto es mucho mejor que

Process took 6.4518549156189 seconds. 
Cuestiones relacionadas