it-swarm.com.de

Verfolgung der Skriptausführungszeit in PHP

PHP muss die CPU-Zeit ermitteln, die ein bestimmtes Skript verwendet hat, um das Limit max_execution_time zu erzwingen. 

Gibt es eine Möglichkeit, im Skript darauf zuzugreifen? Ich würde gerne ein paar Protokolle in meine Tests einbeziehen, wie viel CPU in der eigentlichen PHP verbrannt wurde (die Zeit wird nicht erhöht, wenn das Skript sitzt und auf die Datenbank wartet).

Ich verwende eine Linux-Box. 

234
twk

Auf unixoiden Systemen (und auch in php 7+ unter Windows) können Sie getrusage verwenden:

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

Beachten Sie, dass Sie keine Differenz berechnen müssen, wenn Sie für jeden Test eine PHP-Instanz erzeugen.

190
phihag

Wenn Sie nur die Uhrzeit der Wanduhr und nicht die Ausführungszeit der CPU benötigen, können Sie einfach Folgendes berechnen: 

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

Beachten Sie, dass dies die Zeit einschließt, in der PHP auf externe Ressourcen wie Festplatten oder Datenbanken wartet, die für max_execution_time nicht verwendet wird.

440
talal7860

Kürzere Version der Antwort von 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);

Wie bereits erwähnt, ist dies "Wanduhrzeit" und nicht "CPU-Zeit".

87
C. Lee

Der einfachste Weg:

<?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

Ich habe eine ExecutionTime-Klasse aus der Phihag-Antwort erstellt, die Sie sofort verwenden können:

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

verwendungszweck:

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

Hinweis: In PHP 5 funktioniert die getrusage-Funktion nur in Unix-oid-Systemen. Seit PHP 7 funktioniert es auch unter Windows.

21
Hamid

Gringod von developerfusion.com gibt diese gute Antwort:

<!-- 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"; 
;?>

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

11

Ich denke, du solltest dir xdebug anschauen. Die Profilierungsoptionen geben Ihnen einen Vorsprung, um viele prozessrelevante Elemente zu kennen.

http://www.xdebug.org/

8

Der billigste und schmutzigste Weg ist, einfach microtime()-Anrufe an Stellen in Ihrem Code durchzuführen, an denen Sie Benchmarking durchführen möchten. Machen Sie dies direkt vor und direkt nach den Datenbankabfragen. Es ist einfach, diese Dauer von der restlichen Skriptausführungszeit zu entfernen.

Ein Hinweis: Die Ausführungszeit von PHP ist selten die Ursache für das Timeout Ihres Skripts. Wenn ein Skript ausläuft, handelt es sich fast immer um einen Aufruf an eine externe Ressource.

Dokumentation zu PHP Microtime: http://de.php.net/microtime

8
danieltalsky

Schöner wird es, wenn Sie die Sekunden-Ausgabe folgendermaßen formatieren:

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

wird drucken

Process took 6.45 seconds.

Das ist viel besser als

Process took 6.4518549156189 seconds.
6
Sinan Eldem

Ich habe eine Funktion geschrieben, die die verbleibende Ausführungszeit überprüft.

Warnung: Die Ausführungszeit zählt auf Windows- und Linux-Plattformen unterschiedlich.

/**
 * 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);
}

Mit:

while (true) {
    // so something

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

Möglicherweise möchten Sie nur die Ausführungszeit von Teilen Ihres Skripts erfahren. Der flexibelste Weg, um Teile oder ein komplettes Skript zeitlich zu definieren, besteht darin, drei einfache Funktionen zu erstellen (Verfahrenscode, der hier angegeben ist, aber Sie könnten ihn in eine Klasse umwandeln, indem Sie den Klassentimer {} um ihn herum setzen und einige Anpassungen vornehmen). Dieser Code funktioniert, einfach kopieren und einfügen und ausführen:

$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

Um Minuten und Sekunden anzuzeigen, können Sie Folgendes verwenden:

    $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

Ich habe Hamids Antwort weiter ausgeführt und eine Hilfsklasse geschrieben, die wiederholt gestartet und gestoppt werden kann (zum Profilieren innerhalb einer Schleife).

   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

Als Alternative können Sie diese Zeile einfach in Ihre Codeblöcke einfügen und PHP-Protokolle überprüfen. Für wirklich langsame Funktionen ist das sehr nützlich: 

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

Für ernsthaftes Debuggen verwenden Sie XDebug + Cachegrind unter https://blog.nexcess.net/2011/01/29/diagnosing-slow-php-execution-with-xdebug-and-kcachegrind/

0
Vasili Pascal