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.

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.


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.


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'


74

Cara termudah:

<?php

$time1 = microtime(true);

//script code
//...

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

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

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.


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


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.

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


8

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

http://www.xdebug.org/


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

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.
    }
}

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

1

$_SERVER['REQUEST_TIME']

lihat itu juga. yaitu

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


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

-1

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.