分析PHP脚本最简单的方法是什么?
我喜欢在上面添加一些内容,这些内容显示了所有函数调用的转储以及它们花了多长时间,但我也可以将特定函数放在一边.
我尝试过使用microtime函数:
$then = microtime(); myFunc(); $now = microtime(); echo sprintf("Elapsed: %f", $now-$then);
但这有时会给我带来负面结果.另外,在我的代码中撒上这些东西会很麻烦.
你想要xdebug我想.将它安装在服务器上,打开它,通过kcachegrind(用于linux)或wincachegrind(用于windows)输出输出,它会显示一些漂亮的图表,详细说明确切的时间,计数和内存使用情况(但你会需要另一个扩展).
它严肃地说:D
所述PECL APD扩展的使用如下:
之后,使用解析生成的文件pprofp
.
示例输出:
Trace for /home/dan/testapd.php Total Elapsed Time = 0.00 Total System Time = 0.00 Total User Time = 0.00 Real User System secs/ cumm %Time (excl/cumm) (excl/cumm) (excl/cumm) Calls call s/call Memory Usage Name -------------------------------------------------------------------------------------- 100.0 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0000 0.0009 0 main 56.9 0.00 0.00 0.00 0.00 0.00 0.00 1 0.0005 0.0005 0 apd_set_pprof_trace 28.0 0.00 0.00 0.00 0.00 0.00 0.00 10 0.0000 0.0000 0 preg_replace 14.3 0.00 0.00 0.00 0.00 0.00 0.00 10 0.0000 0.0000 0 str_replace
警告:最新版本的APD日期为2004年,不再维护该扩展,并且存在各种兼容性问题(请参阅注释).
不需要扩展,只需使用这两个函数进行简单的分析.
// Call this at each point of interest, passing a descriptive string function prof_flag($str) { global $prof_timing, $prof_names; $prof_timing[] = microtime(true); $prof_names[] = $str; } // Call this when you're done and want to see the results function prof_print() { global $prof_timing, $prof_names; $size = count($prof_timing); for($i=0;$i<$size - 1; $i++) { echo "{$prof_names[$i]}
"; echo sprintf(" %f
", $prof_timing[$i+1]-$prof_timing[$i]); } echo "{$prof_names[$size-1]}
"; }
下面是一个示例,调用prof_flag(),每个检查点都有一个描述,最后是prof_print():
prof_flag("Start"); include '../lib/database.php'; include '../lib/helper_func.php'; prof_flag("Connect to DB"); connect_to_db(); prof_flag("Perform query"); // Get all the data $select_query = "SELECT * FROM data_table"; $result = mysql_query($select_query); prof_flag("Retrieve data"); $rows = array(); $found_data=false; while($r = mysql_fetch_assoc($result)) { $found_data=true; $rows[] = $r; } prof_flag("Close DB"); mysql_close(); //close database connection prof_flag("Done"); prof_print();
输出如下:
开始
0.004303
连接到DB
0.003518
执行查询
0.000308
检索数据
0.000009
关闭DB
0.000049
完成
从SO文档测试版发布我的参考资料,该测试将脱机.
PHP的扩展名为Xdebug,可用于帮助分析PHP应用程序以及运行时调试.运行探查器时,输出将以二进制格式写入文件"cachegrind".每个平台上都有应用程序来分析这些文件. 不需要更改应用程序代码来执行此分析.
要启用分析,请安装扩展并调整php.ini设置.一些Linux发行版附带标准软件包(例如Ubuntu php-xdebug
软件包).在我们的示例中,我们将根据请求参数可选地运行配置文件.这允许我们保持设置静态并仅在需要时打开探查器.
# php.ini settings # Set to 1 to turn it on for every request xdebug.profiler_enable = 0 # Let's use a GET/POST parameter to turn on the profiler xdebug.profiler_enable_trigger = 1 # The GET/POST value we will pass; empty for any value xdebug.profiler_enable_trigger_value = "" # Output cachegrind files to /tmp so our system cleans them up later xdebug.profiler_output_dir = "/tmp" xdebug.profiler_output_name = "cachegrind.out.%p"
接下来,使用Web客户端向您希望分析的应用程序的URL发出请求,例如
http://example.com/article/1?XDEBUG_PROFILE=1
当页面处理时,它将写入名称类似于的文件
/tmp/cachegrind.out.12345
默认情况下,文件名中的数字是写入它的进程ID.这可以通过xdebug.profiler_output_name
设置进行配置.
请注意,它将为每个执行的PHP请求/进程写入一个文件.因此,例如,如果您希望分析表单帖子,将为GET请求编写一个配置文件以显示HTML表单.需要将XDEBUG_PROFILE参数传递给后续的POST请求,以分析处理表单的第二个请求.因此,在进行性能分析时,有时更容易运行curl直接POST表单.
分析输出
一旦编写,配置文件缓存就可以被诸如KCachegrind或Webgrind之类的应用程序读取.PHPStorm是一种流行的PHP IDE,也可以显示此分析数据.
例如,KCachegrind将显示以下信息:
执行的功能
呼叫时间,包括后续功能调用本身
每个函数被调用的次数
调用图表
源代码链接
要找什么
显然,性能调优对每个应用程序的用例都非常具体.一般来说,寻找:
重复调用您不希望看到的相同功能.对于处理和查询数据的函数,这些可能是应用程序缓存的主要机会.
运行缓慢的功能.申请大部分时间在哪里?性能调优的最佳回报是关注那些消耗最多时间的应用程序部分.
注意:Xdebug,特别是它的分析功能,是非常耗费资源的,并且会降低PHP的执行速度.建议不要在生产服务器环境中运行它们.
如果减去microtimes会给你带来负面结果,请尝试使用带有参数true
(microtime(true)
)的函数.使用时true
,该函数返回一个浮点而不是一个字符串(如果它是在没有参数的情况下调用的话).
老实说,我会争辩说使用NewRelic进行性能分析是最好的.
这是一个PHP扩展,它似乎根本不会减慢运行时间,它们会为您进行监控,允许进行适当的深入挖掘.在昂贵的版本中,它们允许大量钻取(但我们负担不起他们的定价模型).
尽管如此,即使采用免费/标准计划,大多数低悬的水果都显而易见.我也喜欢它可以让你对数据库交互有所了解.
PECL XHPROF也看起来很有意思.它具有可点击的HTML界面,用于查看报告和非常简单的文档.我还没有测试它.
穷人的分析,不需要扩展.支持嵌套的配置文件和总数的百分比:
function p_open($flag) { global $p_times; if (null === $p_times) $p_times = []; if (! array_key_exists($flag, $p_times)) $p_times[$flag] = [ 'total' => 0, 'open' => 0 ]; $p_times[$flag]['open'] = microtime(true); } function p_close($flag) { global $p_times; if (isset($p_times[$flag]['open'])) { $p_times[$flag]['total'] += (microtime(true) - $p_times[$flag]['open']); unset($p_times[$flag]['open']); } } function p_dump() { global $p_times; $dump = []; $sum = 0; foreach ($p_times as $flag => $info) { $dump[$flag]['elapsed'] = $info['total']; $sum += $info['total']; } foreach ($dump as $flag => $info) { $dump[$flag]['percent'] = $dump[$flag]['elapsed']/$sum; } return $dump; }
例:
产量:
array:3 [ "foo" => array:2 [ "elapsed" => 9.000766992569 "percent" => 0.4736904954747 ] "bar" => array:2 [ "elapsed" => 7.0004580020905 "percent" => 0.36841864946596 ] "baz" => array:2 [ "elapsed" => 3.0001420974731 "percent" => 0.15789085505934 ] ]
9> Eric Lamb..:我喜欢使用phpDebug进行性能分析. http://phpdebug.sourceforge.net/www/index.html
它输出所有使用的SQL以及所有包含文件的所有时间/内存使用情况.显然,它最适用于抽象的代码.
对于函数和类分析,我只使用
microtime()
+get_memory_usage()
+get_peak_memory_usage()
.
10> Ali..:我会挑衅地试试BlackFire.
我使用puphpet将这个虚拟框放在一起,测试与BlackFire兼容的不同php框架,如果需要请随意分叉和/或分发:)
https://github.com/webit4me/PHPFrameworks
11> Gary Richard..:对于基准测试,就像您的示例一样,我使用了梨基准测试包。您设置用于测量的标记。该课程还提供了一些演示帮助器,或者您可以根据需要处理数据。
实际上,我使用__destruct方法将其包装在另一个类中。当脚本退出时,输出将通过log4php记录到syslog中,因此我可以使用很多性能数据。