PHPでのスクリプト実行時間の追跡


289

PHPは、max_execution_time制限を適用するために、特定のスクリプトが使用したCPU時間を追跡する必要があります。

スクリプト内でこれにアクセスする方法はありますか?実際のPHPで消費されたCPUの量に関するログをテストに含めたいと思います(スクリプトが座ってデータベースを待機している場合、時間は増加しません)。

Linuxボックスを使用しています。

回答:


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秒かかったページのように、CPU時間は6秒かかったと言っています...これは正しいですか?ここを参照してください:blog.rompe.org/node/85
ダリル・ハイン

@Darryl Hein:ああ、そしてあなたは加算の代わりに文字列連結を使っているので奇妙な結果を得る;)
phihag

@phihagまた、ページが計算に40秒かかりましたが、2秒でロードされたという奇妙な時間を私に与えます。数値は1.4秒から40秒の間で
急上昇する

1
@TimoHuovinen utime/ stime/壁の時計時間について正確にどのような値を取得しますか?また、この動作を示す再現可能な例へのリンクを投稿できますか?OS / phpのバージョン/ウェブサーバーのバージョンは何ですか?いずれにせよ、新しい質問を投稿して、ここにリンクすることができます。
phihag

4
小さな更新を追加するだけです。この機能はWindowsでもサポートされるようになりました。
ankush981 2015年

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時間ではありません。
29:29

18
パーフェクト、私は壁時計の時間追跡ソリューションを探していました。
2016年

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の答えとどう違うのですか...?
ベノマティス

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

結果は数秒で得られませんでした

PHP 5.4.0を使用する必要があります
Joyal 2013

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メモを追加しました。ありがとう
Hamid Tavakoli 2017

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 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つの単純な関数を作成することです(ここでは手順コードを示しますが、クラスタイマーを配置してクラスに変換することもできます}。このコードは機能し、コピーして貼り付けて実行するだけです:

$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

別の方法として、この行をコードブロックに入れて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/を参照してください


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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.