Max_execution_time制限を強制するために、PHPは特定のスクリプトが使用したCPU時間の量を追跡する必要があります。
スクリプト内でこれにアクセスする方法はありますか?実際のPHPでCPUがどれだけ消費されたかについてのテストに、ロギングを含めたいと思います(スクリプトが待機してデータベースを待機しているときは時間は増えません)。
私はLinuxボックスを使っています。
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インスタンスを生成するのであれば、差を計算する必要はありません。
必要なのが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には使用されていないディスクやデータベースなどの外部リソースを待機している時間が含まれます。
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 time'ではなく 'wallclock time'です。
最も簡単な方法:
<?php
$time1 = microtime(true);
//script code
//...
$time2 = microtime(true);
echo 'script execution time: ' . ($time2 - $time1); //value in seconds
<?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";
?>
私はあなたがそのまま使用できる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でも機能します。
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/ )
私はあなたがxdebugを見るべきだと思います。プロファイリングオプションを使用すると、多くのプロセス関連の項目を知ることができます。
これを行う最も安価で最も手間のかからない方法は、単にベンチマークを行いたいコード内の場所でmicrotime()
を呼び出すことです。データベースクエリの前後に実行してください。残りのスクリプト実行時間からこれらの期間を削除するのは簡単です。
ヒント:PHP実行時間がスクリプトのタイムアウトを招くことになることはめったにありません。スクリプトがタイムアウトした場合、ほとんどの場合、外部リソースへの呼び出しになります。
PHPマイクロタイムドキュメント: http://us.php.net/microtime
次のように秒の出力をフォーマットすると、もっときれいになります。
echo "Process took ". number_format(microtime(true) - $start, 2). " seconds.";
印刷します
Process took 6.45 seconds.
これははるかに優れています
Process took 6.4518549156189 seconds.
残りの実行時間をチェックする関数を書きました。
警告:実行時間のカウントは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.
}
}
あなたはあなたのスクリプトの一部の実行時間を知りたいだけかもしれません。パートやスクリプト全体の時間を計る最も柔軟な方法は、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');
分と秒を表示するには、次のようにします。
$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
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";
}
}
別の方法として、この行をコードブロックに入れて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/