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

是否有一种方法可以在脚本中访问它?我希望在测试中包含一些关于实际PHP中消耗了多少CPU的日志记录(当脚本等待数据库时,时间不会增加)。

我用的是Linux机顶盒。


当前回答

我想说的是:

如果测量目标是不同php文件中的两点A和B,会发生什么? 如果我们需要不同的度量,比如基于时间、代码执行持续时间、外部资源访问持续时间,该怎么办? 如果我们需要将我们的度量组织成不同的类别,每个类别都有不同的起点,那该怎么办呢?

正如你怀疑的那样,我们需要一些全局变量来被类对象或静态方法访问:我选择第二种方法,它是:

namespace g3;

class Utils {
   public function __construct() {}

   public static $UtilsDtStart = [];
   public static $UtilsDtStats = [];

   public static function dt() {
      global $UtilsDtStart, $UtilsDtStats;
      $obj = new \stdClass();
      $obj->start = function(int $ndx = 0) use (&$UtilsDtStart) {
         $UtilsDtStart[$ndx] = \microtime(true) * 1000;
      };
      $obj->codeStart = function(int $ndx = 0) use (&$UtilsDtStart) {
         $use = \getrusage();
         $UtilsDtStart[$ndx] = ($use["ru_utime.tv_sec"] * 1000) + ($use["ru_utime.tv_usec"] / 1000);
      };
      $obj->resourceStart = function(int $ndx = 0) use (&$UtilsDtStart) {
         $use = \getrusage();
         $UtilsDtStart[$ndx] = $use["ru_stime.tv_usec"] / 1000;
      };
      $obj->end = function(int $ndx = 0) use (&$UtilsDtStart, &$UtilsDtStats) {
         $t = @$UtilsDtStart[$ndx];
         if($t === null)
            return false;
         $end = \microtime(true) * 1000;
         $dt = $end - $t;
         $UtilsDtStats[$ndx][] = $dt;
         return $dt;
      };
      $obj->codeEnd = function(int $ndx = 0) use (&$UtilsDtStart, &$UtilsDtStats) {
         $t = @$UtilsDtStart[$ndx];
         if($t === null)
            return false;
         $use = \getrusage();
         $dt = ($use["ru_utime.tv_sec"] * 1000) + ($use["ru_utime.tv_usec"] / 1000) - $t;
         $UtilsDtStats[$ndx][] = $dt;
         return $dt;
      };
      $obj->resourceEnd = function(int $ndx = 0) use (&$UtilsDtStart, &$UtilsDtStats) {
         $t = @$UtilsDtStart[$ndx];
         if($t === null)
            return false;
         $use = \getrusage();
         $dt = ($use["ru_stime.tv_usec"] / 1000) - $t;
         $UtilsDtStats[$ndx][] = $dt;
         return $dt;
      };
      $obj->stats = function(int $ndx = 0) use (&$UtilsDtStats) {
         $s = @$UtilsDtStats[$ndx];
         if($s !== null)
            $s = \array_slice($s, 0);
         else
            $s = false;
         return $s;
      };
      $obj->statsLength = function() use (&$UtilsDtStats) {
         return \count($UtilsDtStats);
      };
      return $obj;
   }
}

现在你所要做的就是调用属于特定类别的方法,索引表示它的唯一组:

File A
------
\call_user_func_array(\g3\Utils::dt()->start, [0]);   // point A
...
File B
------
$dt = \call_user_func_array(\g3\Utils::dt()->end, [0]);  // point B

值$dt包含点A和点B之间壁钟持续时间的毫秒数。

估算php代码运行所花费的时间:

File A
------
\call_user_func_array(\g3\Utils::dt()->codeStart, [1]);   // point A
...
File B
------
$dt = \call_user_func_array(\g3\Utils::dt()->codeEnd, [1]);  // point B

注意我们是如何改变传递给方法的索引的。

代码基于从函数返回对象/函数时发生的闭包效应(参见示例中重复的\g3\Utils::dt())。

我用php单元进行了测试,在同一测试文件中的不同测试方法之间,到目前为止它表现良好!

希望这能帮助到别人!

其他回答

如果你像这样格式化秒的输出,它会更漂亮:

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

将打印

Process took 6.45 seconds.

这比

Process took 6.4518549156189 seconds.

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

如果你需要的是挂钟时间,而不是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没有使用这个时间。

我认为您应该看看xdebug。分析选项将为您了解许多与流程相关的项目提供一个良好的开端。

http://www.xdebug.org/

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