web-dev-qa-db-fra.com

Suivi du temps d'exécution du script dans PHP

PHP doit suivre la quantité de temps CPU utilisée par un script particulier pour appliquer la limite max_execution_time. 

Existe-t-il un moyen d'accéder à cela à l'intérieur du script? J'aimerais inclure une certaine journalisation dans mes tests sur la quantité de CPU gravée dans le fichier PHP (le temps n'est pas incrémenté lorsque le script est en attente et attend la base de données).

J'utilise une machine Linux. 

234
twk

Sur les systèmes unixoid (et dans php 7+ sous Windows également), vous pouvez utiliser getrusage , comme:

// 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";

Notez que vous n'avez pas besoin de calculer une différence si vous créez une instance php pour chaque test.

190
phihag

Si tout ce dont vous avez besoin est l'heure de l'horloge murale plutôt que le temps d'exécution de la CPU, le calcul est simple: 

//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 otherwise seconds
$execution_time = ($time_end - $time_start)/60;

//execution time of the script
echo '<b>Total Execution Time:</b> '.$execution_time.' Mins';
// if you get weird results, use number_format((float) $execution_time, 10) 

Notez que cela inclura le temps pendant lequel PHP est assis en attente de ressources externes telles que des disques ou des bases de données, qui ne sont pas utilisées pour max_execution_time.

440
talal7860

Version abrégée de la réponse 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);

Comme indiqué, il s’agit du «temps de l'horloge murale» et non du «temps du processeur

87
C. Lee

Le moyen le plus simple:

<?php

$time1 = microtime(true);

//script code
//...

$time2 = microtime(true);
echo 'script execution time: ' . ($time2 - $time1); //value in seconds
67
joan16v
<?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";
?>
30
Joyal

J'ai créé une classe ExecutionTime en réponse phihag que vous pouvez utiliser en sortie de boîte:

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";
     }
 }

usage:

$executionTime = new ExecutionTime();
$executionTime->start();
// code
$executionTime->end();
echo $executionTime;

Remarque: Dans PHP 5, la fonction getrusage ne fonctionne que sur les systèmes Unix-oid. Depuis PHP 7, cela fonctionne aussi sous Windows.

21
Hamid

Gringod de developerfusion.com donne cette bonne réponse:

<!-- 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/ )

11
lencho patasplanas

Je pense que vous devriez regarder xdebug. Les options de profilage vous donneront une longueur d'avance sur la connaissance de nombreux éléments liés au processus.

http://www.xdebug.org/

8
Stewart Robinson

La méthode la moins chère et la plus sale consiste simplement à faire des appels microtime() aux endroits de votre code que vous souhaitez comparer. Faites-le juste avant et juste après les requêtes de base de données et il est simple de supprimer ces durées du reste de votre temps d'exécution de script.

Un indice: votre temps d'exécution PHP sera rarement ce qui fera expirer votre script. Si un script expire, il s'agira presque toujours d'un appel à une ressource externe.

Documentation PHP microtime: http://us.php.net/microtime

8
danieltalsky

Cela va être plus joli si vous formatez la sortie secondes comme:

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

imprimera

Process took 6.45 seconds.

C'est beaucoup mieux que

Process took 6.4518549156189 seconds.
6
Sinan Eldem

J'ai écrit une fonction qui vérifie le temps d'exécution restant.

Attention: Le comptage du temps d'exécution est différent sous Windows et sous 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);
}

En utilisant:

while (true) {
    // so something

    if (!isRemainingMaxExecutionTimeBiggerThan(5000)) {
        // Time to die.
        // Safely close DB and done the iteration.
    }
}
2
Martin

Vous voudrez peut-être uniquement connaître l'heure d'exécution de certaines parties de votre script. La manière la plus flexible de chronométrer des parties ou un script entier est de créer 3 fonctions simples (code de procédure indiqué ici, mais vous pouvez le transformer en classe en mettant le temporisateur de classe {} autour de celui-ci et en effectuant quelques modifications). Ce code fonctionne, il suffit de copier-coller et d'exécuter:

$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
JG Estiot

Pour afficher les minutes et les secondes, vous pouvez utiliser:

    $startTime = microtime(true);
    $endTime = microtime(true);
    $diff = round($endTime - $startTime);
    $minutes = floor($diff / 60); //only minutes
    $seconds = $diff % 60;//remaining seconds, using modulo operator
    echo "script execution time: minutes:$minutes, seconds:$seconds"; //value in seconds
0
Aris

En développant davantage la réponse de Hamid, j'ai écrit une classe d'assistance qui peut être démarrée et arrêtée de manière répétée (pour le profilage dans une boucle).

   class ExecutionTime
   {
      private $startTime;
      private $endTime;
      private $compTime = 0;
      private $sysTime = 0;

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

      public function End(){
         $this->endTime = getrusage();
         $this->compTime += $this->runTime($this->endTime, $this->startTime, "utime");
         $this->systemTime += $this->runTime($this->endTime, $this->startTime, "stime");
      }

      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->compTime . " ms for its computations\n" .
                "It spent " . $this->systemTime . " ms in system calls\n";
      }
   }
0
Oded

En guise d'alternative, vous pouvez simplement mettre cette ligne dans vos blocs de code et consulter les journaux php. Pour les fonctions très lentes, c'est très utile: 

trigger_error("Task done at ". strftime('%H:%m:%S', time()), E_USER_NOTICE); 

Pour le débogage sérieux, utilisez XDebug + Cachegrind, voir https://blog.nexcess.net/2011/01/29/diagnosing-slow-php-execution-with-xdebug-and-kcachegrind/

0
Vasili Pascal