分析 PHP 脚本的最简单方法

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21133/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:12:17  来源:igfitidea点击:

Simplest way to profile a PHP script

phpprofiling

提问by Mark Biek

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

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

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 microtimefunction:

我尝试尝试使用microtime函数:

$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.

但这有时会给我带来负面结果。另外,把它洒在我的代码上很麻烦。

采纳答案by Vincent

The PECL APDextension is used as follows:

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

<?php
apd_set_pprof_trace();

//rest of the script
?>

After, parse the generated file using pprofp.

之后,使用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 maintainedand has various compability issues (see comments).

警告:APD 的最新版本发布于 2004 年,扩展不再维护并且存在各种兼容性问题(见评论)。

回答by mercutio

You want xdebugI 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).

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

It rocks, seriously :D

它真的很摇滚:D

回答by TimH - Codidact

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("&nbsp;&nbsp;&nbsp;%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() 并在最后调用 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();

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

启动
   0.004303
连接数据库
   0.003518
执行查询
   0.000308
检索数据
   0.000009
关闭数据库
   0.000049
完成

回答by Matt S

Cross posting my reference from SO Documentation beta which is going offline.

从 SO Documentation beta 版交叉发布我的参考资料,该版本即将脱机。

Profiling with XDebug

使用 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.

一个名为 Xdebug 的 PHP 扩展可用于帮助分析 PHP 应用程序以及运行时调试。运行探查器时,输出以称为“cachegrind”的二进制格式写入文件。每个平台上都有应用程序来分析这些文件。 执行此分析不需要更改应用程序代码。

To enable profiling, install the extension and adjust php.ini settings. Some Linux distributions come with standard packages (e.g. Ubuntu's php-xdebugpackage). 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 设置。一些 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"

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

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

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_namesetting.

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

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.

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

Analyzing the Output

分析输出

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

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

KCachegrind

KCachegrind

KCachegrind, for example, will display information including:

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

  • 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.

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

回答by luka

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).

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

回答by zeroasterisk

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

老实说,我要争辩说使用 NewRelic 进行分析是最好的。

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).

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

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

分析时其中一个界面的屏幕截图

回答by bishop

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

回答by Josef Sábl

PECL XHPROFlooks interensting too. It has clickable HTML interfacefor viewing reports and pretty straightforward documentation. I have yet to test it though.

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

回答by Eric Lamb

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

我喜欢使用 phpDebug 进行分析。 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.

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

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

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

回答by Ali

I would defiantly give BlackFirea try.

我会挑衅地尝试BlackFire

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 :)

我使用puphpet将这个 virtualBox 放在一起,以测试BlackFire 附带的不同 php 框架,如果需要,请随时分叉和/或分发:)

https://github.com/webit4me/PHPFrameworks

https://github.com/webit4me/PHPFrameworks