代码之家  ›  专栏  ›  技术社区  ›  twk Mark Adler

在PHP中跟踪脚本执行时间

  •  235
  • twk Mark Adler  · 技术社区  · 16 年前

    PHP必须跟踪特定脚本用于强制执行最大执行时间限制的CPU时间量。

    有没有办法在脚本内部访问这个?我想在测试中包括一些日志记录,测试实际PHP中CPU的消耗量(当脚本坐着等待数据库时,时间不会增加)。

    我使用的是Linux设备。

    15 回复  |  直到 6 年前
        1
  •  189
  •   phihag    7 年前

    在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实例,则不需要计算差异。

        2
  •  437
  •   benomatis    7 年前

    如果您所需要的只是墙上的时钟时间,而不是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在sat上等待外部资源(如磁盘或数据库)的时间,而这些资源不用于最大执行时间。

        3
  •  86
  •   C. Lee    11 年前

    塔拉尔7860答案的较短版本

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

        4
  •  67
  •   joan16v    9 年前

    最简单的方法:

    <?php
    
    $time1 = microtime(true);
    
    //script code
    //...
    
    $time2 = microtime(true);
    echo 'script execution time: ' . ($time2 - $time1); //value in seconds
    
        5
  •  29
  •   Joyal    12 年前
    <?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";
    ?>
    
        6
  •  21
  •   Timo Tijhof avalkab    6 年前

    我从phihag answer中创建了一个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系统中工作。从PHP7开始,它也可以在Windows上运行。

        7
  •  11
  •   lencho patasplanas    12 年前

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

        8
  •  8
  •   danieltalsky    16 年前

    最便宜和最脏的方法就是简单地做 microtime() 在您的代码中您想要基准测试的地方调用。在数据库查询之前和之后都要这样做,从脚本的其余执行时间中删除这些持续时间很简单。

    提示:您的PHP执行时间很少会导致脚本超时。如果脚本超时,它几乎总是调用外部资源。

    PHP微时间文档: http://us.php.net/microtime

        9
  •  8
  •   Stewart Robinson    16 年前

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

    http://www.xdebug.org/

        10
  •  6
  •   Sinan Eldem    7 年前

    如果将秒输出格式设置为:

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

    将打印

    Process took 6.45 seconds.
    

    这比

    Process took 6.4518549156189 seconds.
    
        11
  •  2
  •   Martin    8 年前

    我编写了一个检查剩余执行时间的函数。

    警告: 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.
        }
    }
    
        12
  •  1
  •   JG Estiot    9 年前

    您可能只想知道脚本部分的执行时间。对部分或整个脚本计时最灵活的方法是创建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');
    
        13
  •  0
  •   Vasili Pascal    7 年前

    作为一种替代方法,您可以将这行代码放入代码块中并检查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/

        14
  •  0
  •   Oded    6 年前

    进一步扩展了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";
          }
       }
    
        15
  •  0
  •   Aris    6 年前

    要显示分钟和秒,可以使用:

        $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