分析 PHP 脚本的最简单方法

发布于 2024-07-04 09:56:21 字数 338 浏览 7 评论 0原文

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

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

我尝试尝试 microtime 函数:

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

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

但这有时会给我带来负面结果。 另外,将其撒在我的代码中会很麻烦。

What's the easiest way to profile a PHP script?

I'd love tacking something on that shows me a dump of all function calls and how long they took but I'm also OK with putting something around specific functions.

I tried experimenting with the microtime function:

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

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

but that sometimes gives me negative results. Plus it's a lot of trouble to sprinkle that all over my code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(14

趁年轻赶紧闹 2024-07-11 09:56:21

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

真的很震撼:D

You want xdebug I think. Install it on the server, turn it on, pump the output through kcachegrind (for linux) or wincachegrind (for windows) and it'll show you a few pretty charts that detail the exact timings, counts and memory usage (but you'll need another extension for that).

It rocks, seriously :D

街角卖回忆 2024-07-11 09:56:21

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

// 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("   %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< br>关闭数据库
   0.000049
完成

No extensions are needed, just use these two functions for simple profiling.

// 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("   %f<br>", $prof_timing[$i+1]-$prof_timing[$i]);
    }
    echo "<b>{$prof_names[$size-1]}</b><br>";
}

Here is an example, calling prof_flag() with a description at each checkpoint, and prof_print() at the end:

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

Output looks like this:

Start
   0.004303
Connect to DB
   0.003518
Perform query
   0.000308
Retrieve data
   0.000009
Close DB
   0.000049
Done

望笑 2024-07-11 09:56:21

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 年,扩展不再维护 并且存在各种兼容性问题(请参阅评论)。

The PECL APD extension is used as follows:

<?php
apd_set_pprof_trace();

//rest of the script
?>

After, parse the generated file using pprofp.

Example output:

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

Warning: the latest release of APD is dated 2004, the extension is no longer maintained and has various compability issues (see comments).

无所谓啦 2024-07-11 09:56:21

使用 XDebug 进行分析

名为 Xdebug 的 PHP 扩展可帮助分析 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 来直接发布表单会更容易。

分析输出

一旦写入,配置文件缓存就可以由应用程序读取,例如KCachegrind 或 Webgrind。 PHPStorm 是一种流行的 PHP IDE,也可以显示此分析数据

KCachegrind

例如,KCachegrind 将显示的信息包括:

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

要查找的内容

性能调整是针对每个应用程序的用例的。 一般来说,最好查找一下:

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

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

Profiling with XDebug

An extension to PHP called Xdebug is available to assist in profiling PHP applications, as well as runtime debugging. When running the profiler, the output is written to a file in a binary format called "cachegrind". Applications are available on each platform to analyze these files. No application code changes are necessary to perform this profiling.

To enable profiling, install the extension and adjust php.ini settings. Some Linux distributions come with standard packages (e.g. Ubuntu's php-xdebug package). In our example we will run the profile optionally based on a request parameter. This allows us to keep settings static and turn on the profiler only as needed.

# 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"

Next use a web client to make a request to your application's URL you wish to profile, e.g.

http://example.com/article/1?XDEBUG_PROFILE=1

As the page processes it will write to a file with a name similar to

/tmp/cachegrind.out.12345

By default the number in the filename is the process id which wrote it. This is configurable with the xdebug.profiler_output_name setting.

Note that it will write one file for each PHP request / process that is executed. So, for example, if you wish to analyze a form post, one profile will be written for the GET request to display the HTML form. The XDEBUG_PROFILE parameter will need to be passed into the subsequent POST request to analyze the second request which processes the form. Therefore when profiling it is sometimes easier to run curl to POST a form directly.

Analyzing the Output

Once written the profile cache can be read by an application such as KCachegrind or Webgrind. PHPStorm, a popular PHP IDE, can also display this profiling data.

KCachegrind

KCachegrind, for example, will display information including:

  • Functions executed
  • Call time, both itself and inclusive of subsequent function calls
  • Number of times each function is called
  • Call graphs
  • Links to source code

What to Look For

Obviously performance tuning is very specific to each application's use cases. In general it's good to look for:

  • Repeated calls to the same function you wouldn't expect to see. For functions that process and query data these could be prime opportunities for your application to cache.
  • Slow-running functions. Where is the application spending most of its time? the best payoff in performance tuning is focusing on those parts of the application which consume the most time.

Note: Xdebug, and in particular its profiling features, are very resource intensive and slow down PHP execution. It is recommended to not run these in a production server environment.

原谅我要高飞 2024-07-11 09:56:21

如果减去 microtime 得到负结果,请尝试使用带有参数 true 的函数 (microtime(true))。 使用 true 时,该函数返回浮点数而不是字符串(就像不带参数调用它一样)。

If subtracting microtimes gives you negative results, try using the function with the argument true (microtime(true)). With true, the function returns a float instead of a string (as it does if it is called without arguments).

一袭白衣梦中忆 2024-07-11 09:56:21

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

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

尽管如此,即使使用免费/标准计划,大多数容易实现的目标也是显而易见且简单的。 我还喜欢它也可以让您了解数据库交互。

分析时界面之一的屏幕截图

Honestly, I am going to argue that using NewRelic for profiling is the best.

It's a PHP extension which doesn't seem to slow down runtime at all and they do the monitoring for you, allowing decent drill down. In the expensive version they allow heavy drill down (but we can't afford their pricing model).

Still, even with the free/standard plan, it's obvious and simple where most of the low hanging fruit is. I also like that it can give you an idea on DB interactions too.

screenshot of one of the interfaces when profiling

黯然#的苍凉 2024-07-11 09:56:21

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

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

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

输入图像描述这里

You all should definitely check this new php profiler.

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

It redefines the way of how php profilers collects and presents the result.
Instead of outputting just a total number of particular function calls and total time spent of executing it - PHP-SPX presents the whole timeline of request execution in a perfectly readable way. Below is the screen of GUI it provides.

enter image description here

橘味果▽酱 2024-07-11 09:56:21

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

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

Poor man's profiling, no extensions required. Supports nested profiles and percent of total:

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

Example:

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

Yields:

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
  ]
]
十秒萌定你 2024-07-11 09:56:21

PECL XHPROF 看起来也很有趣。 它具有可点击的 HTML 界面,用于查看报告,并且非常简单< a href="http://mirror.facebook.net/facebook/xhprof/doc.html" rel="noreferrer">文档。 不过我还没有测试过。

PECL XHPROF looks interensting too. It has clickable HTML interface for viewing reports and pretty straightforward documentation. I have yet to test it though.

我喜欢麦丽素 2024-07-11 09:56:21

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

它始终输出/ 使用的任何 SQL 以及所有包含的文件的内存使用情况。 显然,它最适合抽象的代码。

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

I like to use phpDebug for profiling.
http://phpdebug.sourceforge.net/www/index.html

It outputs all time / memory usage for any SQL used as well as all the included files. Obviously, it works best on code that's abstracted.

For function and class profiling I'll just use microtime() + get_memory_usage() + get_peak_memory_usage().

暖风昔人 2024-07-11 09:56:21

我会坚决尝试 BlackFire

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

https://github.com/webit4me/PHPFrameworks

I would defiantly give BlackFire a try.

There is this virtualBox I've put together using puphpet, to test different php frameworks which coms with BlackFire, please feel free to fork and/or distribute if required :)

https://github.com/webit4me/PHPFrameworks

一花一树开 2024-07-11 09:56:21

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

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

For benchmarking, like in your example, I use the pear Benchmark package. You set markers for measuring. The class also provides a few presentation helpers, or you can process the data as you see fit.

I actually have it wrapped in another class with a __destruct method. When a script exits, the output is logged via log4php to syslog, so I have a lot of performance data to work from.

﹎☆浅夏丿初晴 2024-07-11 09:56:21

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

XDebug is not stable and it's not always available for particular php version. For example on some servers I still run php-5.1.6, -- it's what comes with RedHat RHEL5 (and btw still receives updates for all important issues), and recent XDebug does not even compile with this php. So I ended up with switching to DBG debugger
Its php benchmarking provides timing for functions, methods, modules and even lines.

亢潮 2024-07-11 09:56:21

如果您是 VS Code 的粉丝,这里有一个快速且简单(免费)的扩展 PHP 分析器

这为您提供了简单的函数调用时间和热路径
在代码中突出显示。

PHP 热VS Code 中的路径

更多详细信息https:// docs.devsense.com/vscode/profiling

In case you're a fan of VS Code, there is a quick and simple (free) extension PHP Profiler.

This gives you simple function call times and hotpaths
highlighting right in your code.

PHP hot paths in VS Code

More details: https://docs.devsense.com/vscode/profiling

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文