【问题标题】:Simplest way to profile a PHP script分析 PHP 脚本的最简单方法
【发布时间】:2010-09-06 11:23:06
【问题描述】:

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

我很想添加一些东西,显示所有函数调用的转储以及它们花费了多长时间,但我也可以在特定函数周围添加一些东西。

我尝试使用microtime 函数:

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

echo sprintf("Elapsed:  %f", $now-$then);

但这有时会给我带来负面的结果。另外,在我的代码中到处乱写是很麻烦的。

【问题讨论】:

  • 嘿,马克,看看这个评论来帮助你解决负面的 cmets:ro.php.net/manual/en/function.microtime.php#99524
  • @Midiane 链接的评论没有意义。如果它似乎解决了评论者的问题,那一定是巧合。仅使用microtime() 有时会导致评估表达式,如:"0.00154800 1342892546" - "0.99905700 1342892545",其评估结果为:0.001548 - 0.999057。你可以使用microtime( TRUE ) 来避免这个问题,就像@luka 的pointed out

标签: php profiling


【解决方案1】:

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

真的很厉害:D

【讨论】:

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

无需扩展,只需使用这两个函数进行简单的分析即可。

// 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>";
}

这是一个示例,在每个检查点调用 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
连接到数据库
   0.003518
执行查询
   0.000308
检索数据
   0.000009
关闭数据库
   0.000049
完成

【讨论】:

    【解决方案3】:

    PECL APD 扩展名的用法如下:

    <?php
    apd_set_pprof_trace();
    
    //rest of the script
    ?>
    

    之后,使用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 年发布的,扩展名为 is no longer maintained,并且存在各种兼容性问题(请参阅 cmets)。

    【讨论】:

    • APD 扩展在 php 5.4 上被破坏。
    • 对 user457015 的反驳是,我能够让它在运行 wordpress 3.8.1 和 PHP 5.3.10 的网站上运行,它似乎运行良好。
    • @Supernovah,user457015 确实说过 PHP 5.4。他没有说它在 PHP 5.3 上被破坏了。
    • @user1420752 我正在运行 5.3.27,但它也没有在那里运行。我收到一个未定义的函数错误。
    • 最新版本的 APD 是从 2004 年开始的(!)它不适用于 PHP 7。当尝试使用 pecl install apd 安装 PHP 5 时,它会给出关于“config.m4”的错误消息。看来您必须从源代码安装它,我还没有尝试过。说真的,是不是有一个现代的、更新的基于 CLI 的 PHP 分析工具,它与 Homebrew 一起安装,需要最少的设置并提供易于人类阅读的输出?
    【解决方案4】:

    交叉发布我从 SO Documentation beta 中离线的参考。

    使用 XDebug 进行分析

    一个名为 Xdebug 的 PHP 扩展可用于协助profiling PHP applications 以及运行时调试。运行探查器时,输出以称为“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"
    

    接下来使用网络客户端向您希望分析的应用程序的 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 表单会更容易。

    分析输出

    配置文件缓存一旦写入,就可以被KCachegrindWebgrind 等应用程序读取。 PHPStorm,一个流行的PHP IDE,也可以display this profiling data.

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

    • 执行的函数
    • 调用时间,包括其本身和后续函数调用的时间
    • 每个函数的调用次数
    • 调用图
    • 源代码链接

    寻找什么

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

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

    注意:Xdebug,尤其是它的分析功能,是非常耗费资源的,并且会减慢 PHP 的执行速度。建议不要在生产服务器环境中运行这些。

    【讨论】:

    • 添加到解析配置文件缓存的工具列表:PhpStorm 还有一个预览配置文件缓存的工具
    • @peter 我忘了 PHPStorm 有这个功能。我已将其添加到文档的链接。谢谢!
    • 有什么方法可以直接在服务器上获取文本(非 GUI)报告?
    • @Mark 你能把这个标记为答案吗?当前的答案即使在发布后也已过时,并且多年来一直没有用。这确实有效,我知道没有更好的方法。
    【解决方案5】:

    如果减去微时间会给您带来负面结果,请尝试使用带有参数true (microtime(true)) 的函数。使用true,该函数返回一个浮点数而不是一个字符串(就像在不带参数的情况下调用它一样)。

    【讨论】:

      【解决方案6】:

      老实说,我认为使用 NewRelic 进行分析是最好的。

      这是一个 PHP 扩展,它似乎根本不会减慢运行时的速度,并且它们会为您进行监控,从而可以进行适当的钻取。在昂贵的版本中,他们允许进行大量深入研究(但我们负担不起他们的定价模型)。

      尽管如此,即使使用免费/标准计划,大多数低悬的成果都显而易见且简单。我也喜欢它也可以让您了解数据库交互。

      【讨论】:

      • New Relic 看起来很有希望,当然。然而,他们Privacy Policy 中的“披露您的应用程序数据”部分立即让我反感。恕我直言,与第三方共享专有源代码有点太多了。
      • 这里没有跳过他们的防御,但看起来“应用程序数据”只是性能信息和系统配置信息,而不是您的应用程序源代码。
      • 我的新遗物 99% 的时间都显示我的“WebTransaction”,并且没有“ApplicationTraces”的专业帐户
      • 尝试注册:newrelic.com/rackspace
      • 在你的服务器上安装新的 relic 之前备份你的原始 php 配置,因为它会大量更新 php 配置。
      【解决方案7】:

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

      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;
      }
      

      例子:

      <?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());
      

      产量:

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

      【讨论】:

        【解决方案8】:

        你们都应该检查这个新的 php profiler。

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

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

        【讨论】:

        • 太棒了!简直太棒了!
        • 我喜欢这种设置的简单性
        • 这很有趣,因为我第一次听说这个工具。当我试图在 mac 上设置它时,运行make 命令会抛出错误,说not targets specified and no makefile found。所以需要更多地挖掘来解决这些问题。
        【解决方案9】:

        PECL XHPROF 看起来也很有趣。它有clickable HTML interface 用于查看报告和非常简单的documentation。不过我还没有测试它。

        【讨论】:

        • 看起来它没有得到太多的爱。 2009 年的最后一次更新,没有适用于 5.3、5.4 及更高版本的 PEAR 包...
        • Facebook 通过 php 5.5 创建了一个支持分支 github.com/facebook/xhprof
        • 检查这个分支也提出了一些额外的调整:github.com/preinheimer/xhprof
        • xhprof.io 为使用 XHProf 收集的数据提供 GUI,并能够将数据存储在数据库中以进行历史分析。我是后者实现的作者。
        • 好像更新了一些细节。首先,pecl 现在提到该项目的主页是github,并且它正在积极更新。此扩展将生成分析数据,但要对其进行可视化,需要另一个包。我正在对此进行测试,并将在此处使用所需的 GUI 工具进行更新。
        【解决方案10】:

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

        它输出所有使用的 SQL 以及所有包含的文件的所有时间/内存使用情况。显然,它在抽象的代码上效果最好。

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

        【讨论】:

          【解决方案11】:

          我会大胆尝试BlackFire

          我使用puphpet 组装了这个 virtualBox,用于测试与 BlackFire 兼容的不同 php 框架,如果需要,请随时 fork 和/或分发 :)

          https://github.com/webit4me/PHPFrameworks

          【讨论】:

          • blackfire 不错,他们也有破解版,可以免费使用(功能有限)。但是,如果您是在代理后面工作的开发人员,那么这可能会很困难,因为这需要启用一些标头才能使其正常工作,如果开发运营/安全团队不想允许,这可能会很困难。
          【解决方案12】:

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

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

          【讨论】:

            【解决方案13】:

            XDebug 不稳定,它并不总是适用于特定的 php 版本。例如,在某些服务器上,我仍然运行 php-5.1.6,——它是 RedHat RHEL5 附带的(顺便说一句,所有重要问题仍会收到更新),最近的 XDebug 甚至无法使用这个 php 编译。所以我最终切换到DBG debugger 它的php benchmarking 为函数、方法、模块甚至行提供了时序。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-07-30
              • 2011-05-21
              • 2013-09-24
              • 2018-07-25
              • 2012-06-25
              • 2023-04-06
              • 2011-04-11
              相关资源
              最近更新 更多