跟踪PHP中的脚本执行时间


289

PHP必须跟踪特定脚本使用的CPU时间,以强制执行max_execution_time限制。

有没有办法在脚本中访问此内容?我想在测试中包括一些日志记录,以了解实际PHP中的CPU消耗了多少(脚本坐着并等待数据库时,时间没有增加)。

我正在使用Linux机器。

Answers:


237

在unixoid系统上(以及在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秒的页面说要花费6s的CPU时间...这是正确的吗?看到这里:blog.rompe.org/node/85
Darryl Hein

@Darryl Hein:哦,您会得到奇怪的结果,因为您使用的是字符串串联而不是加法;)
phihag

@phihag也给了我奇怪的时间,一个页面花了40秒的计算时间,但是在2秒内加载了。数量趋于1.4秒40秒之间跳跃
蒂莫Huovinen

1
@TimoHuovinen您在utime/ stime时钟时间里到底得到了什么值?并且您可以发布指向可复制示例的链接,以显示此行为吗?您在哪个OS / php版本/ webserver版本上?无论如何,您可能想发布一个新问题并在此处链接到它。
phihag,2012年

4
只需添加一个小更新:Windows现在也支持此功能。
ankush981

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 2012年

18
太好了,我一直在寻找挂钟时间跟踪解决方案。
萨米尔斯'16

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时间”


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

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

我没有在几秒钟内得到结果

您应该使用PHP 5.4.0
Joyal

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.工程
马丁·Driel

@MartinvanDriel我附加了便条。谢谢
哈米德·塔瓦科利

3
我想如果您将开始放在构造函数中,然后放在tostring结束,则每次使用都需要少两行代码。OOP +1
toddmo '18

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 microtime文档:http : //us.php.net/microtime


8

我认为您应该看看xdebug。概要分析选项将使您在了解许多与过程相关的项目上有一个良好的开端。

http://www.xdebug.org/


1
只要确保您没有在有很多网站的生产服务器上安装xdebug。它产生大量的日志记录,并且可能使小型SSD驱动器不堪重负。
Corgalore 2015年

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

1

您可能只想知道脚本各部分的执行时间。对部分或整个脚本进行计时的最灵活方法是创建3个简单函数(此处提供了过程代码,但您可以通过在其周围放置class timer {}并进行一些调整来将其变成一个类)。此代码有效,只需复制并粘贴并运行:

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

也去看看。即

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


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

返回microtime(true)-$ _SERVER [“ REQUEST_TIME_FLOAT”];

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.