为了强制执行max_execution_time限制,PHP必须跟踪特定脚本所使用的CPU时间。
是否有一种方法可以在脚本中访问它?我希望在测试中包含一些关于实际PHP中消耗了多少CPU的日志记录(当脚本等待数据库时,时间不会增加)。
我用的是Linux机顶盒。
为了强制执行max_execution_time限制,PHP必须跟踪特定脚本所使用的CPU时间。
是否有一种方法可以在脚本中访问它?我希望在测试中包含一些关于实际PHP中消耗了多少CPU的日志记录(当脚本等待数据库时,时间不会增加)。
我用的是Linux机顶盒。
当前回答
这里列出了几种方法。但每个人都有自己的优点和缺点。而且(在我看来)所有较长的答案的可读性都很糟糕。
所以我决定把这些都放在一个答案中,这是容易使用和阅读的。
使用
$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 =以微秒计。 电视= ??不知道
其他回答
如果你需要的是挂钟时间,而不是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没有使用这个时间。
最便宜也是最麻烦的方法是在代码中想要进行基准测试的地方进行microtime()调用。在数据库查询之前和之后执行它,从脚本执行时间的其余部分中删除这些持续时间就很简单了。
提示:PHP执行时间很少会导致脚本超时。如果一个脚本超时,它几乎总是调用外部资源。
PHP微时间文档: http://us.php.net/microtime
在页面底部居中打印的小脚本,在服务器调用时以微秒精度开始脚本执行。
为了不扭曲结果,并与页面中的内容100%兼容,我使用浏览器端本地javascript代码段在页面上编写结果。
//Uncomment the line below to test with 2 seconds
//usleep(2000000);
$prec = 5; // numbers after comma
$time = number_format(microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'], $prec, '.', '');
echo "<script>
if(!tI) {
var tI=document.createElement('div');
tI.style.fontSize='8px';
tI.style.marginBottom='5px';
tI.style.position='absolute';
tI.style.bottom='0px';
tI.style.textAlign='center';
tI.style.width='98%';
document.body.appendChild(tI);
}
tI.innerHTML='$time';
</script>";
另一种方法是使代码片段尽可能小,并使用样式表中的类对其进行样式化。
替换回显…;与以下部分分开: echo "<script>if(!tI){var tI=document.createElement('div');tI. classname ='ldtme';document.body.appendChild(tI);}tI. innerhtml ='$time'; 在CSS中创建并填充.ldtme{…}类。
<?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";
?>
您可能只想知道部分脚本的执行时间。为部分或整个脚本计时的最灵活的方法是创建3个简单的函数(这里给出了过程代码,但您可以通过在它周围放置类timer{}并进行一些调整将其转换为类)。这段代码工作,只需复制粘贴并运行:
$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');