PHP에서 스크립트 실행 시간 추적


289

PHP는 max_execution_time 제한을 적용하기 위해 특정 스크립트가 사용한 CPU 시간을 추적해야합니다.

스크립트 안에서 이것에 접근 할 수있는 방법이 있습니까? 실제 PHP에서 CPU가 얼마나 많이 태워 졌는지에 대한 테스트와 함께 로깅을 포함하고 싶습니다 (스크립트가 앉아서 데이터베이스를 기다리는 경우 시간이 증가하지 않음).

Linux 상자를 사용하고 있습니다.

답변:


238

유닉스 시스템 (및 Windows의 PHP 7 이상)에서는 다음 과 같이 getrusage 를 사용할 수 있습니다 .

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

모든 테스트에 대해 PHP 인스턴스를 생성하는 경우 차이를 계산할 필요가 없습니다.


스크립트 시작시의 값에서 끝의 값을 빼야합니까? 내가하지 않으면 정말 이상한 숫자가 나타납니다. 생성하는 데 0.05 초가 걸린 페이지처럼 CPU 시간이 6 초가 걸렸다 고 말하는 것처럼 ... 정확합니까? 여기를 참조하십시오 : blog.rompe.org/node/85
대릴 하인

@Darryl Hein : 아, 그리고 대신 문자열 연결을 사용하기 때문에 이상한 결과를 얻습니다;)
phihag

@phihag 또한 페이지를 계산하는 데 40 초가 걸렸지 만 2 초 만에로드되는 이상한 시간을줍니다. 수는 1.4 초 40 초 사이를 이동하는 경향이있다
티모 Huovinen

1
@TimoHuovinen utime/ stime/ wall 시계 시간에 정확히 어떤 값을 얻 습니까? 이 동작을 보여주는 재현 가능한 예제에 대한 링크를 게시 할 수 있습니까? 어떤 OS / php 버전 / 웹 서버 버전입니까? 어쨌든 새 질문을 게시하고 여기에 링크 할 수 있습니다.
phihag

4
작은 업데이트 만 추가 :이 기능은 이제 Windows에서도 지원됩니다.
ankush981 2016 년

522

CPU 실행 시간이 아닌 벽시계 시간 만 있으면 다음과 같이 간단하게 계산할 수 있습니다.

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

여기에는 PHP가 max_execution_time에 사용되지 않는 디스크 또는 데이터베이스와 같은 외부 리소스를 기다리는 시간이 포함됩니다.


38
안녕하세요-CPU 시간이 아닌 '벽시계 시간'을 추적합니다.
twk

18
완벽합니다. 저는 벽시계 시간 추적 솔루션을 찾고있었습니다.
samiles

118

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

지적했듯이, 이것은 'cpu 시간'이 아닌 'wallclock time'입니다.


74

가장 쉬운 방법 :

<?php

$time1 = microtime(true);

//script code
//...

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

9
이것은 talal7860의 대답과 어떻게 다른가요?
benomatis

@webeno 그는 60.로 나누지 않습니다 . 실제로 아무런 차이 가 없습니다 .
A1rPun

[어떻게 2] 어떻게이 답변에 다운 보트가 없습니까? 위의 답변과 동일합니다.
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";
?>

나는 초에 결과를하지 않았다


29

즉시 사용 가능한 phihag 답변에서 ExecutionTime 클래스를 만들었습니다.

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

용법:

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

참고 : PHP 5에서 getrusage 함수는 Unix-oid 시스템에서만 작동합니다. PHP 7부터는 Windows에서도 작동합니다.


2
참고 : Windows getrusage에서는 PHP 7부터 작동합니다.
Martin van Driel

@MartinvanDriel 메모를 추가했습니다. 감사합니다
Hamid Tavakoli

3
생성자에서 시작하고 tostring으로 끝나는 경우 각 사용법에는 2 줄의 코드가 더 필요합니다. OOP의 경우 +1
toddmo

13

developerfusion.com의 Gringod는 다음과 같은 좋은 답변을 제공합니다.

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

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


11

다음과 같이 초 출력을 형식화하면 더 아름답습니다.

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

인쇄합니다

Process took 6.45 seconds.

이보다 훨씬 낫다

Process took 6.4518549156189 seconds.

9

가장 저렴하고 더러운 방법은 microtime()코드에서 벤치마킹하려는 위치를 호출 하는 것입니다 . 데이터베이스 쿼리 직전과 직후에 수행하면 나머지 스크립트 실행 시간에서 해당 기간을 제거하는 것이 간단합니다.

힌트 : PHP 실행 시간이 스크립트 시간을 초과하는 일은 거의 없습니다. 스크립트가 시간 초과되면 거의 항상 외부 리소스를 호출하게됩니다.

PHP 마이크로 타임 문서 : http://us.php.net/microtime


8

나는 당신이 xdebug를 봐야한다고 생각합니다. 프로파일 링 옵션을 사용하면 많은 공정 관련 항목을 파악할 수 있습니다.

http://www.xdebug.org/


1
웹 사이트가 많은 프로덕션 서버에 xdebug를 설치하지 마십시오. 엄청난 양의 로깅을 생성하며 소형 SSD 드라이브를 압도 할 수 있습니다.
Corgalore

8

분과 초를 표시하려면 다음을 사용할 수 있습니다.

    $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

남은 실행 시간을 확인하는 함수를 작성했습니다.

경고 : 실행 시간 계산은 Windows 및 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);
}

사용 :

while (true) {
    // so something

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

2

$_SERVER['REQUEST_TIME']

그것도 확인하십시오. 즉

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

흥미롭게 $_SERVER['REQUEST_TIME']도 php-cli (서버가없는 곳)에서도 가능합니다
hanshenrik

1

스크립트 부분의 실행 시간 만 알고 싶을 수도 있습니다. 부분 또는 전체 스크립트를 시간에 가장 유연하게 적용하는 방법은 간단한 함수 3 개를 작성하는 것입니다 (프로 시저 코드는 여기에 있지만 클래스 타이머 {}를 둘러싼 후 몇 가지 조정하면 클래스로 바꿀 수 있습니다). 이 코드는 복사하여 붙여 넣은 다음 작동합니다.

$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의 답변을 더 확장하면서 루프에서 프로파일 링하기 위해 반복적으로 시작하고 중지 할 수있는 도우미 클래스를 작성했습니다.

   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

마이크로 타임 반환 (true)-$ _SERVER [ "REQUEST_TIME_FLOAT"];

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.