Theo dõi thời gian thực thi tập lệnh trong PHP


289

PHP phải theo dõi lượng thời gian CPU mà một tập lệnh cụ thể đã sử dụng để thực thi giới hạn max_execut_time.

Có cách nào để có quyền truy cập vào bên trong tập lệnh này không? Tôi muốn bao gồm một số ghi nhật ký với các thử nghiệm của tôi về số lượng CPU đã bị cháy trong PHP thực tế (thời gian không tăng lên khi tập lệnh đang ngồi và chờ cơ sở dữ liệu).

Tôi đang sử dụng hộp Linux.

Câu trả lời:


237

Trên các hệ thống unixoid (và trong php 7+ trên Windows), bạn có thể sử dụng getrusage , như:

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

Lưu ý rằng bạn không cần tính toán chênh lệch nếu bạn sinh ra một cá thể php cho mọi thử nghiệm.


Giá trị ở cuối có nên được trừ khỏi giá trị ở đầu tập lệnh không? Tôi sẽ nhận được một số con số thực sự kỳ lạ nếu tôi không. Giống như một trang mất 0,05 giây để tạo ra nói rằng phải mất 6 giây thời gian của CPU ... điều này có đúng không? Xem tại đây: blog.rompe.org/node/85
Darryl Hein

@Darryl Hein: Ồ, và bạn nhận được kết quả kỳ lạ vì bạn đang sử dụng nối chuỗi thay vì bổ sung;)
phihag

@phihag Cũng cho tôi những khoảng thời gian kỳ lạ, rằng một trang mất 40 giây tính toán nhưng được tải trong 2 giây. Con số có xu hướng nhảy trong khoảng từ 1,4 giây đến 40 giây
Timo Huovinen

1
@TimoHuovinen Giá trị chính xác mà bạn nhận được cho utime/ stime/ thời gian đồng hồ treo tường là gì? Và bạn có thể gửi một liên kết đến một ví dụ tái sản xuất cho thấy hành vi này? Trên phiên bản OS / php / webserver nào? Trong mọi trường hợp, bạn có thể muốn gửi một câu hỏi mới và liên kết đến nó ở đây.
phihag

4
Chỉ cần thêm một bản cập nhật nhỏ: Chức năng này hiện cũng được hỗ trợ trên Windows.
ankush981

522

Nếu tất cả những gì bạn cần là thời gian đồng hồ treo tường, thay vì thời gian thực hiện CPU, thì thật đơn giản để tính toán:

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

Lưu ý rằng điều này sẽ bao gồm thời gian mà PHP đang chờ đợi các tài nguyên bên ngoài như đĩa hoặc cơ sở dữ liệu, vốn không được sử dụng cho max_execut_time.


38
Xin chào - điều này theo dõi 'thời gian đồng hồ' - không phải thời gian CPU.
twk

18
Hoàn hảo, tôi đang tìm kiếm một giải pháp theo dõi thời gian wallclock.
samiles

118

Phiên bản ngắn hơn của câu trả lời của 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);

Như đã chỉ ra, đây là 'thời gian treo tường' chứ không phải 'thời gian cpu'


74

Cách dễ nhất:

<?php

$time1 = microtime(true);

//script code
//...

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

9
Điều này khác với câu trả lời của Talal7860 như thế nào ...?
benomatis 18/03/18

@webeno Anh ấy không chia cho 60.. Thực sự không có gì khác biệt.
A1rPun

[làm thế nào 2] làm thế nào câu trả lời này không có bất kỳ downvote? Nó giống như câu trả lời ở trên.
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";
?>

Tôi đã không nhận được kết quả sau vài giây

Bạn nên sử dụng PHP 5.4.0
Joyalty

29

Tôi đã tạo một lớp ExecutTime ngoài câu trả lời phihag mà bạn có thể sử dụng ngoài hộp:

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

sử dụng:

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

Lưu ý: Trong PHP 5, hàm getrusage chỉ hoạt động trong các hệ thống Unix-oid. Kể từ PHP 7, nó cũng hoạt động trên Windows.


2
Lưu ý: Trên Windows getrusagechỉ hoạt động kể từ PHP 7.
Martin van Driel

@MartinvanDriel Tôi đã thêm ghi chú. Cảm ơn
Hamid Tavakoli

3
Tôi đoán nếu bạn đặt start trong constructor và kết thúc chuỗi, mỗi lần sử dụng sẽ cần ít hơn 2 dòng mã. +1 cho OOP
chập chững

13

Gringod tại developerfusion.com đưa ra câu trả lời hay này:

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

Từ ( http://www.developerfusion.com/code/2058/determine-execut-time-in-php/ )


11

Sẽ đẹp hơn nếu bạn định dạng đầu ra giây như:

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

sẽ in

Process took 6.45 seconds.

Điều này tốt hơn nhiều

Process took 6.4518549156189 seconds.

9

Cách rẻ nhất và bẩn nhất để làm điều đó chỉ đơn giản là thực hiện microtime() cuộc gọi tại các địa điểm trong mã của bạn mà bạn muốn điểm chuẩn. Thực hiện ngay trước và ngay sau khi truy vấn cơ sở dữ liệu và thật đơn giản để loại bỏ các khoảng thời gian đó khỏi phần còn lại của thời gian thực thi tập lệnh của bạn.

Một gợi ý: thời gian thực thi PHP của bạn hiếm khi trở thành thứ khiến cho kịch bản của bạn hết thời gian chờ. Nếu một kịch bản hết thời gian, nó hầu như sẽ luôn là một cuộc gọi đến một tài nguyên bên ngoài.

Tài liệu microtime PHP: http://us.php.net/microtime


8

Tôi nghĩ bạn nên nhìn vào xdebug. Các tùy chọn định hình sẽ giúp bạn bắt đầu tìm hiểu nhiều mục liên quan đến quá trình.

http://www.xdebug.org/


1
Chỉ cần đảm bảo rằng bạn không cài đặt xdebug trên máy chủ sản xuất có nhiều trang web. Nó tạo ra một lượng đăng nhập khổng lồ và có thể áp đảo một ổ SSD nhỏ.
Corgalore

8

Để hiển thị phút và giây bạn có thể sử dụng:

    $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

Tôi đã viết một chức năng kiểm tra thời gian thực hiện còn lại.

Cảnh báo: Đếm thời gian thực hiện là khác nhau trên Windows và trên nền tảng 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);
}

Sử dụng:

while (true) {
    // so something

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

1

Bạn có thể chỉ muốn biết thời gian thực hiện các phần của tập lệnh của bạn. Cách linh hoạt nhất để các bộ phận thời gian hoặc toàn bộ tập lệnh là tạo 3 hàm đơn giản (mã thủ tục được đưa ra ở đây nhưng bạn có thể biến nó thành một lớp bằng cách đặt bộ đếm thời gian lớp {} xung quanh nó và thực hiện một vài điều chỉnh). Mã này hoạt động, chỉ cần sao chép và dán và chạy:

$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']

kiểm tra điều đó quá I E

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


0

Mở rộng hơn nữa về câu trả lời của Hamid, tôi đã viết một lớp người trợ giúp có thể được bắt đầu và dừng lại nhiều lần (để định hình bên trong một vòng lặp).

   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

trả lại microtime (đúng) - $ _SERVER ["REQUEST_TIME_FLOAT"];

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.