PHP'de betik yürütme süresini izleme


289

PHP, max_execution_time sınırını zorlamak için belirli bir komut dosyasının kullandığı CPU zamanı miktarını izlemelidir.

Komut dosyasının içinde buna erişmenin bir yolu var mı? Ben gerçek PHP ne kadar CPU yanmış hakkında benim testleri ile bazı günlüğü dahil etmek istiyorum (zaman script oturan ve veritabanı beklerken zaman artmaz).

Linux kutusu kullanıyorum.

Yanıtlar:


238

Unixoid sistemlerde (ve Windows'ta da php 7+'da) getrusage'i kullanabilirsiniz , örneğin:

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

Her test için bir php örneği üretiyorsanız, bir fark hesaplamanıza gerek olmadığını unutmayın.


Sondaki değer komut dosyasının başındaki değerden çıkarılmalı mıdır? Yapmazsam gerçekten tuhaf rakamlar alıyorum. Oluşturmak için 0,05 saniye süren bir sayfanın 6 saniyelik CPU zamanı aldığını söylüyor gibi ... bu doğru mu? Buraya bakın: blog.rompe.org/node/85
Darryl Hein

@Darryl Hein: Oh, ve garip sonuçlar elde edersiniz çünkü ekleme yerine dize birleştirme kullanıyorsunuz;)
phihag

@phihag Ayrıca garip zamanlar veriyor, bir sayfanın hesaplamalarda 40 saniye sürdüğü ancak 2 saniyede yüklendiği. Rakam 1,4 saniye ile 40 saniye arasında atlama eğilimindedir
Timo Huovinen

1
@TimoHuovinen utime/ stime/ duvar saati zamanı için tam olarak hangi değerleri elde edersiniz ? Ve bu davranışı gösteren çoğaltılabilir bir örneğe bağlantı gönderebilir misiniz ? Hangi OS / php sürümü / web sunucusu sürümünde kullanıyorsunuz? Her durumda, yeni bir soru göndermek ve buraya bağlantı vermek isteyebilirsiniz.
phihag

4
Sadece küçük bir güncelleme eklemek: Bu işlev artık Windows'ta da destekleniyor.
ankush981

522

İhtiyacınız olan tek şey CPU yürütme zamanı yerine duvar saati zamanı ise, hesaplamak kolaydır:

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

Bunun PHP'nin diskler veya veritabanları gibi max_execution_time için kullanılmayan harici kaynaklar için beklediği süreyi içereceğini unutmayın.


38
Merhaba - CPU zamanını değil, 'wallclock zamanını' izler.
twk

18
Mükemmel, bir duvar saati zaman izleme çözümü arıyordum.
samiles

118

Talal7860'ın cevabının daha kısa versiyonu

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

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

Belirtildiği gibi, bu 'cpu zamanı' değil 'duvar saati zamanı'


74

En kolay yol:

<?php

$time1 = microtime(true);

//script code
//...

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

9
bu talal7860'ın cevabından nasıl farklı ...?
benomatis

@webeno Bölünmez 60.. Gerçekten fark yok.
A1rPun

[nasıl 2] bu cevabın nasıl iniş puanı yok? yukarıdaki cevapla aynı.
T.Todua

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

Saniyeler içinde sonuç alamadım

PHP 5.4.0
Joyal

29

Kutusundan kullanabileceğiniz filog yanıtı dışında bir ExecutionTime sınıfı oluşturdum:

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

kullanımı:

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

Not: PHP 5'de getrusage işlevi yalnızca Unix-oid sistemlerinde çalışır. PHP 7'den beri Windows üzerinde de çalışır.


2
Not: Windows'da getrusageyalnızca PHP 7'den beri çalışır.
Martin van Driel

@MartinvanDriel Notu ekledim. Teşekkürler
Hamid Tavakoli

3
Sanırım yapıcıya başlar ve tostring biter, her kullanım 2 daha az kod satırı gerekir. OOP için +1
toddmo

13

Developerfusion.com'da Gringod bu iyi cevabı veriyor:

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

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


11

Saniye çıkışını aşağıdaki gibi biçimlendirirseniz daha güzel olur:

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

yazdıracak

Process took 6.45 seconds.

Bu çok daha iyi

Process took 6.4518549156189 seconds.

9

Bunu yapmanın en ucuz ve en kirli yolu microtime(), kodunuzda karşılaştırmak istediğiniz yerlere arama yapmaktır . Veritabanı sorgularından hemen önce ve hemen sonra yapın ve bu süreleri kod yürütme sürenizin geri kalanından kaldırmak kolaydır.

Bir ipucu: PHP yürütme zamanınız nadiren komut dosyası zaman aşımı yapan şey olacaktır. Bir komut dosyası zaman aşımına uğrarsa, neredeyse her zaman harici bir kaynağa çağrı olur.

PHP mikrotime belgeleri: http://us.php.net/microtime


8

Sanırım xdebug'a bakmalısın. Profil oluşturma seçenekleri, işlemle ilgili birçok öğeyi tanımak için size bir başlangıç ​​sağlayacaktır.

http://www.xdebug.org/


1
Sadece xdebug'u birçok web sitesine sahip bir üretim sunucusuna yüklemediğinizden emin olun. Çok büyük miktarda günlük kaydı oluşturur ve küçük bir SSD sürücüyü bunaltabilir.
15'te Corgalore

8

Dakikaları ve saniyeleri göstermek için şunları kullanabilirsiniz:

    $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

2

Kalan yürütme süresini kontrol eden bir fonksiyon yazdım.

Uyarı: Yürütme süresi sayımı Windows ve Linux platformunda farklıdır.

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

Kullanımı:

while (true) {
    // so something

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

2

$_SERVER['REQUEST_TIME']

Bunu da kontrol et. yani

...
// your codes running
...
echo (time() - $_SERVER['REQUEST_TIME']);

ilginç $_SERVER['REQUEST_TIME']php-cli (sunucu yok) da mevcuttur
hanshenrik

1

Komut dosyanızın yalnızca bölümlerinin yürütme süresini bilmek isteyebilirsiniz. Parçaları veya bir komut dosyasının tamamını zamanlamanın en esnek yolu, 3 basit işlev oluşturmaktır (burada verilen prosedür kodu, ancak {} sınıf zamanlayıcısını etrafına koyarak ve birkaç değişiklik yaparak bir sınıfa dönüştürebilirsiniz). Bu kod çalışır, sadece kopyalayıp yapıştırın ve çalıştırın:

$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');


0

Hamid'in cevabını daha da genişleterek, tekrar tekrar başlatılabilen ve durdurulabilecek bir yardımcı sınıf yazdım (bir döngü içinde profil oluşturmak için).

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

-1

dönüş mikro zamanı (true) - $ _SERVER ["REQUEST_TIME_FLOAT"];

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.