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

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

我用的是Linux机顶盒。


当前回答

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

http://www.xdebug.org/

其他回答

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

作为一种替代方法,你可以把这一行放在你的代码块中,并检查php日志,对于非常慢的函数,它非常有用:

trigger_error("Task done at ". strftime('%H:%m:%S', time()), E_USER_NOTICE); 

严肃的调试使用XDebug + Cachegrind,请参见https://blog.nexcess.net/2011/01/29/diagnosing-slow-php-execution-with-xdebug-and-kcachegrind/

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

正如所指出的,这是“wallclock时间”而不是“cpu时间”

这里列出了几种方法。但每个人都有自己的优点和缺点。而且(在我看来)所有较长的答案的可读性都很糟糕。

所以我决定把这些都放在一个答案中,这是容易使用和阅读的。

使用

$start = get_timers();
for( $i = 0; $i < 100000; $i++ ){
  // Code to check
}
$end = get_timers();
display_timer_statistics( $start, $end );

函数定义

function display_timer_statistics( $start_timers, $end_timers ){

    // Settings
    $key_width = '100px';
    $decimals = 4;
    $decimals_wallclock = $decimals;
    $decimals_request_time_float = $decimals;

    // Variables
    $start_resource_usage_timer = $start_timers[0];
    $start_wallclock = $start_timers[1];
    $end_resource_usage_timer = $end_timers[0];
    $end_wallclock = $end_timers[1];

    // # User time
    // Add seconds and microseconds for the start/end, and subtract from another
    $end_user_time_seconds = $end_resource_usage_timer["ru_utime.tv_sec"]*1000;
    $end_user_time_microseconds = intval($end_resource_usage_timer["ru_utime.tv_usec"]/1000);
    $start_user_time_seconds = $start_resource_usage_timer["ru_utime.tv_sec"]*1000;
    $start_user_time_microseconds = intval($start_resource_usage_timer["ru_utime.tv_usec"]/1000);
    $total_user_time = ($end_user_time_seconds + $end_user_time_microseconds) - ($start_user_time_seconds + $start_user_time_microseconds);

    // # System time
    // Add seconds and microseconds for the start/end, and subtract from another
    $end_system_time_seconds = $end_resource_usage_timer["ru_stime.tv_sec"]*1000;
    $end_system_time_microseconds = intval($end_resource_usage_timer["ru_stime.tv_usec"]/1000);
    $start_system_time_seconds = $start_resource_usage_timer["ru_stime.tv_sec"]*1000;
    $start_system_time_microseconds = intval($start_resource_usage_timer["ru_stime.tv_usec"]/1000);
    $total_system_time = ($end_system_time_seconds + $end_system_time_microseconds) - ($start_system_time_seconds + $start_system_time_microseconds);

    // Wallclock
    $total_wallclock_time = number_format( ( $end_wallclock - $start_wallclock), $decimals_wallclock );

    // Server request_time_float
    $request_time_float = microtime(true) - $_SERVER["REQUEST_TIME_FLOAT"];
    $request_time_float = number_format( $request_time_float, $decimals_request_time_float );

    // Print
    $span_start = "<span style='width: $key_width; display: inline-block;'>";
    $span_end = "</span>";

    $output = "# RUNTIME AND TIMERS " . PHP_EOL ;
    $output .= PHP_EOL;
    $output .= $span_start . $total_user_time . $span_end . " User time (utime)" . PHP_EOL;
    $output .= $span_start . $total_system_time . $span_end . " System time (stime)" . PHP_EOL;
    $output .= PHP_EOL;
    $output .= $span_start . $total_wallclock_time . $span_end . " Wallclock" . PHP_EOL;
    $output .= PHP_EOL;
    $output .= $span_start . $request_time_float . $span_end . " REQUEST_TIME_FLOAT" . PHP_EOL . PHP_EOL . PHP_EOL;

    echo nl2br( $output );
}

function get_timers(){
    return [ getrusage(), microtime( true ) ];
}

术语表

这些都是从PHP文档中获取的

挂钟=花了多长时间 ru =资源使用率 utime =用户使用的时间 stime =使用的系统时间 tv_sec =秒。 tv_usec =以微秒计。 电视= ??不知道

进一步扩展Hamid的回答,我写了一个可以重复启动和停止的helper类(用于在循环中进行分析)。

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