分析PHP脚本的最简单方法

Mar*_*iek 284 php profiling

分析PHP脚本最简单的方法是什么?

我喜欢在上面添加一些内容,这些内容显示了所有函数调用的转储以及它们花了多长时间,但我也可以将特定函数放在一边.

我尝试过使用microtime函数:

$then = microtime();
myFunc();
$now = microtime();

echo sprintf("Elapsed:  %f", $now-$then);
Run Code Online (Sandbox Code Playgroud)

但这有时会给我带来负面结果.另外,在我的代码中撒上这些东西会很麻烦.

mer*_*tio 264

你想要xdebug我想.将它安装在服务器上,打开它,通过kcachegrind(用于linux)或wincachegrind(用于windows)输出输出,它会显示一些漂亮的图表,详细说明确切的时间,计数和内存使用情况(但你会需要另一个扩展).

它严肃地说:D

  • xdebug + webgrind迅速成为我快速轻松分析的首选武器.http://code.google.com/p/webgrind/ (52认同)
  • 我发现这比APD解决方案更容易实现.但也许那是因为由于某些原因APD在我的系统上没有正确编译.kcachegrind的图表也像承诺的那样漂亮. (6认同)
  • xdebug + xdebug_start_trace()+ xdebug_stop_trace()= win (4认同)
  • 使用XAMPP很容易在Windows上工作.已经为xdebug配置了netbeans.您需要做的唯一事情是将php.ini中的xdebug设置更改为xdebug.profiler_output_name ="cachegrind.out.%t-%s",否则将不会生成任何输出.需要重启apache. (3认同)
  • 这应该是最佳/公认的答案。我花了半个小时才让所有事情都正常工作(从源代码编译 xdebug)。坚实的建议。 (2认同)

Vin*_*ent 104

所述PECL APD扩展的使用如下:

<?php
apd_set_pprof_trace();

//rest of the script
?>
Run Code Online (Sandbox Code Playgroud)

之后,使用解析生成的文件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
Run Code Online (Sandbox Code Playgroud)

警告:最新版本的APD日期为2004年,不再维护该扩展,并且存在各种兼容性问题(请参阅注释).

  • 在PHP 5.4上打破了APD扩展. (18认同)
  • 最新版本的APD是从2004年开始的(!)它不适用于PHP 7.当尝试使用`pecl install apd`安装PHP 5时,它会显示有关"config.m4"的错误消息.好像你必须从源代码安装它,我还没有尝试过.说真的,是不是有一个现代的,更新的基于CLI的PHP分析工具,与Homebrew一起安装,需要最少的设置并提供易于人类可读的输出? (2认同)

Tim*_*ica 90

不需要扩展,只需使用这两个函数进行简单的分析.

// 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 "<b>{$prof_names[$i]}</b><br>";
        echo sprintf("&nbsp;&nbsp;&nbsp;%f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}
Run Code Online (Sandbox Code Playgroud)

下面是一个示例,调用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();
Run Code Online (Sandbox Code Playgroud)

输出如下:

开始
   0.004303
连接到DB
   0.003518
执行查询
   0.000308
检索数据
   0.000009
关闭DB
   0.000049
完成


Mat*_*t S 32

从SO文档测试版发布我的参考资料,该测试将脱机.

使用XDebug进行分析

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"
Run Code Online (Sandbox Code Playgroud)

接下来,使用Web客户端向您希望分析的应用程序的URL发出请求,例如

http://example.com/article/1?XDEBUG_PROFILE=1
Run Code Online (Sandbox Code Playgroud)

当页面处理时,它将写入名称类似于的文件

/tmp/cachegrind.out.12345
Run Code Online (Sandbox Code Playgroud)

默认情况下,文件名中的数字是写入它的进程ID.这可以通过xdebug.profiler_output_name设置进行配置.

请注意,它将为每个执行的PHP请求/进程写入一个文件.因此,例如,如果您希望分析表单帖子,将为GET请求编写一个配置文件以显示HTML表单.需要将XDEBUG_PROFILE参数传递给后续的POST请求,以分析处理表单的第二个请求.因此,在进行性能分析时,有时更容易运行curl直接POST表单.

分析输出

一旦编写,配置文件缓存就可以被诸如KCachegrindWebgrind之类的应用程序读取.PHPStorm是一种流行的PHP IDE,也可以显示此分析数据.

KCachegrind

例如,KCachegrind将显示以下信息:

  • 执行的功能
  • 呼叫时间,包括后续功能调用本身
  • 每个函数被调用的次数
  • 调用图表
  • 源代码链接

要找什么

显然,性能调优对每个应用程序的用例都非常具体.一般来说,寻找:

  • 重复调用您不希望看到的相同功能.对于处理和查询数据的函数,这些可能是应用程序缓存的主要机会.
  • 运行缓慢的功能.申请大部分时间在哪里?性能调优的最佳回报是关注那些消耗最多时间的应用程序部分.

注意:Xdebug,特别是它的分析功能,是非常耗费资源的,并且会降低PHP的执行速度.建议不要在生产服务器环境中运行它们.

  • 添加到分析配置文件缓存的工具列表中:PhpStorm还提供了一个预览配置文件缓存的工具 (2认同)

小智 24

如果减去microtimes会给你带来负面结果,请尝试使用带有参数true(microtime(true))的函数.使用时true,该函数返回一个浮点而不是一个字符串(如果它是在没有参数的情况下调用的话).


zer*_*isk 24

老实说,我会争辩说使用NewRelic进行性能分析是最好的.

这是一个PHP扩展,它似乎根本不会减慢运行时间,它们会为您进行监控,允许进行适当的深入挖掘.在昂贵的版本中,它们允许大量钻取(但我们负担不起他们的定价模型).

尽管如此,即使采用免费/标准计划,大多数低悬的水果都显而易见.我也喜欢它可以让你对数据库交互有所了解.

分析时其中一个接口的屏幕截图

  • 肯定,New Relic看起来很有前途.但是,"隐私政策"(https://newrelic.com/privacy)中的"披露您的应用程序数据"部分立即击退了我.Imho,与第三方分享**专有**源代码片段有点太多了. (16认同)
  • 在这里没有跳跃到他们的防守,但看起来"应用程序数据"只是性能信息和系统配置信息,而不是您的应用程序源代码. (8认同)

Jos*_*ábl 13

PECL XHPROF也看起来很有意思.它具有可点击的HTML界面,用于查看报告和非常简单的文档.我还没有测试它.


Jac*_*ski 13

你们都应该检查这个新的 php 分析器。

https://github.com/NoiseByNorthwest/php-spx

它重新定义了 php 分析器收集和呈现结果的方式。PHP-SPX 不是只输出特定函数调用的总数和执行它所花费的总时间 - PHP-SPX 以一种完全可读的方式呈现请求执行的整个时间线。下面是它提供的 GUI 屏幕。

在此处输入图片说明

  • 惊人的!简直太神奇了! (3认同)

bis*_*hop 12

穷人的分析,不需要扩展.支持嵌套的配置文件和总数的百分比:

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;
}
Run Code Online (Sandbox Code Playgroud)

例:

<?php

p_open('foo');
sleep(1);
p_open('bar');
sleep(2);
p_open('baz');
sleep(3);
p_close('baz');
sleep(2);
p_close('bar');
sleep(1);
p_close('foo');

var_dump(p_dump());
Run Code Online (Sandbox Code Playgroud)

产量:

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
  ]
]
Run Code Online (Sandbox Code Playgroud)


Eri*_*amb 10

我喜欢使用phpDebug进行性能分析. http://phpdebug.sourceforge.net/www/index.html

它输出所有使用的SQL以及所有包含文件的所有时间/内存使用情况.显然,它最适用于抽象的代码.

对于函数和类分析,我只使用microtime()+ get_memory_usage()+ get_peak_memory_usage().


Ali*_*Ali 7

我会挑衅地试试BlackFire.

我使用puphpet将这个虚拟框放在一起,测试与BlackFire兼容的不同php框架,如果需要请随意分叉和/或分发:)

https://github.com/webit4me/PHPFrameworks


Gar*_*son 6

对于基准测试,就像您的示例一样,我使用了梨基准测试包。您设置用于测量的标记。该课程还提供了一些演示帮助器,或者您可以根据需要处理数据。

实际上,我使用__destruct方法将其包装在另一个类中。当脚本退出时,输出将通过log4php记录到syslog中,因此我可以使用很多性能数据。