Melacak waktu eksekusi skrip dalam PHP

289

PHP harus melacak jumlah waktu CPU yang digunakan skrip tertentu untuk menerapkan batas max_execution_time.

Apakah ada cara untuk mendapatkan akses ke dalam skrip ini? Saya ingin memasukkan beberapa logging dengan tes saya tentang berapa banyak CPU dibakar dalam PHP yang sebenarnya (waktu tidak bertambah ketika skrip sedang duduk dan menunggu database).

Saya menggunakan kotak Linux.

twk
sumber

Jawaban:

237

Pada sistem unixoid (dan di php 7+ di Windows juga), Anda dapat menggunakan getrusage , seperti:

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

Perhatikan bahwa Anda tidak perlu menghitung perbedaan jika Anda menelurkan contoh php untuk setiap tes.

phihag
sumber
Haruskah nilai di akhir dikurangi dari nilai di awal skrip? Saya mendapatkan beberapa angka yang sangat aneh jika tidak. Seperti halaman yang membutuhkan waktu 0,05 detik untuk menghasilkan mengatakan butuh waktu CPU 6 s ... apakah ini benar? Lihat di sini: blog.rompe.org/node/85
Darryl Hein
@Darryl Hein: Oh, dan Anda mendapatkan hasil yang aneh karena Anda menggunakan penggabungan string, bukan penambahan;)
phihag
@ Phihag Juga memberi saya waktu yang aneh, bahwa satu halaman membutuhkan waktu 40 detik dalam perhitungan tetapi dimuat dalam 2 detik. Jumlahnya cenderung melonjak antara 1,4 detik dan 40 detik
Timo Huovinen
1
@TimoHuovinen Nilai apa yang sebenarnya Anda dapatkan untuk utime/ stime/ waktu jam dinding? Dan dapatkah Anda memposting tautan ke contoh yang dapat direproduksi yang memperlihatkan perilaku ini? Pada OS / versi php / versi server web apa Anda? Bagaimanapun, Anda mungkin ingin memposting pertanyaan baru dan tautan ke sini.
phihag
4
Hanya menambahkan pembaruan kecil: Fungsi ini sekarang juga didukung pada Windows.
ankush981
522

Jika yang Anda butuhkan adalah waktu dinding, bukan waktu eksekusi CPU, maka mudah untuk menghitung:

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

Perhatikan bahwa ini akan termasuk waktu ketika PHP duduk menunggu sumber daya eksternal seperti disk atau database, yang tidak digunakan untuk max_execution_time.

talal7860
sumber
38
Hai - ini melacak 'waktu wallclock' - bukan waktu CPU.
twk
18
Sempurna, saya sedang mencari solusi pelacakan waktu tempuh.
Samiles
118

Versi lebih pendek dari jawaban 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);

Seperti yang ditunjukkan, ini adalah 'waktu wallclock' bukan 'waktu cpu'

C. Lee
sumber
74

Cara termudah:

<?php

$time1 = microtime(true);

//script code
//...

$time2 = microtime(true);
echo 'script execution time: ' . ($time2 - $time1); //value in seconds
joan16v
sumber
9
apa bedanya dengan jawaban talal7860 ...?
benomatis
@webeno Dia tidak membagi dengan 60.. Tidak ada perbedaan.
A1rPun
[bagaimana 2] bagaimana jawaban ini tidak memiliki downvotes? sama dengan jawaban di atas.
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";
?>
Setia
sumber
Saya tidak mendapatkan hasil dalam hitungan detik
Anda harus menggunakan PHP 5.4.0
Joyal
29

Saya membuat kelas ExecutionTime dari jawaban phihag yang dapat Anda gunakan di luar kotak:

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

pemakaian:

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

Catatan: Di PHP 5, fungsi getrusage hanya berfungsi di sistem Unix-oid. Sejak PHP 7, ini juga berfungsi pada Windows.

Hamid Tavakoli
sumber
2
Catatan: Di Windows getrusagehanya berfungsi sejak PHP 7.
Martin van Driel
@ MartinvanDriel saya menambahkan catatan itu. Terima kasih
Hamid Tavakoli
3
Saya kira jika Anda meletakkan mulai di konstruktor, dan berakhir di tostring, setiap penggunaan akan membutuhkan 2 baris kode kurang. +1 untuk OOP
toddmo
13

Gringod di developerfusion.com memberikan jawaban yang bagus:

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

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

patasplanas lencho
sumber
11

Ini akan menjadi lebih cantik jika Anda memformat output detik seperti:

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

akan dicetak

Process took 6.45 seconds.

Ini jauh lebih baik daripada

Process took 6.4518549156189 seconds.
Sinan Eldem
sumber
9

Cara termurah dan paling kotor untuk melakukannya adalah dengan microtime()menelepon di tempat-tempat dalam kode yang ingin Anda tolak. Lakukan dengan benar sebelum dan sesudah permintaan basis data dan mudah untuk menghapus jangka waktu tersebut dari sisa waktu eksekusi skrip Anda.

Sebuah petunjuk: waktu eksekusi PHP Anda jarang menjadi hal yang membuat waktu script Anda habis. Jika skrip berakhir, itu hampir selalu akan menjadi panggilan ke sumber daya eksternal.

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

danieltalsky
sumber
8

Saya pikir Anda harus melihat xdebug. Opsi pembuatan profil akan memberi Anda awal untuk mengetahui banyak item terkait proses.

http://www.xdebug.org/

Stewart Robinson
sumber
1
Pastikan Anda tidak menginstal xdebug di server produksi dengan banyak situs web. Ini menghasilkan sejumlah besar penebangan dan dapat membanjiri drive SSD kecil.
Corgalore
8

Untuk menampilkan menit dan detik, Anda dapat menggunakan:

    $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
Aris
sumber
2

Saya menulis fungsi yang memeriksa sisa waktu eksekusi.

Peringatan: Penghitungan waktu eksekusi berbeda pada platform Windows dan 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);
}

Menggunakan:

while (true) {
    // so something

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

Anda mungkin hanya ingin tahu waktu pelaksanaan bagian skrip Anda. Cara paling fleksibel untuk menentukan waktu bagian atau keseluruhan skrip adalah dengan membuat 3 fungsi sederhana (kode prosedural yang diberikan di sini tetapi Anda dapat mengubahnya menjadi kelas dengan meletakkan timer kelas {} di sekitarnya dan membuat beberapa tweak). Kode ini berfungsi, cukup salin dan tempel dan jalankan:

$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');
JG Estiot
sumber
1

$_SERVER['REQUEST_TIME']

lihat itu juga. yaitu

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

Lebih lanjut memperluas jawaban Hamid, saya menulis kelas pembantu yang dapat dimulai dan dihentikan berulang kali (untuk membuat profil di dalam lingkaran).

   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";
      }
   }
Oded
sumber
-1

return microtime (true) - $ _SERVER ["REQUEST_TIME_FLOAT"];

ICP
sumber