PHP性能分析工具xhprof介绍、安装、使用说明

PHPABC PHP开发 1,930 次浏览 , , 没有评论

为什么使用xhprof?

我们在开发中虽然微观上去控制每一个逻辑的最佳算法,可能了解数据结构之后会去分析一个小段脚本的时间复杂度和空间复杂度,但是我们很难从宏观上去分析一个系统的执行性能与执行流程,以及程序执行的瓶颈。当被问到“你如何去分析一个PHP应用的性能,以及程序的瓶颈是什么的时候”,会不会很尴尬呢?其实PHP性能分析工具有多种可以选择,下面我来说说我使用的xhprof。

XHProf (A Hierarchical Profiler For PHP)是一个轻量级的分层性能测量分析器,是C实现的PHP Zend扩展,最初是facebook的大神们写的,是分层的函数调用级别的分析函数执行的时间、CPU计算时间、内存消耗的PHP性能分析工具。XHProf 除了用C实现的Zend扩展之外,还有一个PHP实现的界面,使得查看XHProf分析结果变得更加容易。

安装xhprof

1
2
3
4
5
6
7
8
9
10
11
$>wget http://pecl.php.net/get/xhprof-0.9.4.tgz

$>tar zxvf xhprof-0.9.4.tgz

$>cd xhprof-0.9.4/extension

$>/Library/WebServer/php-5.4/bin/phpize

$>./configure --with-php-config=/Library/WebServer/php-5.4/bin/php-config

$>make && make install

xhprof运行时配置

php.ini中加入

1
2
extension=xhprof.so
xhprof.output_dir=/Users/xudianyang/Server/var/run/xhprof

其中xhprof.output_dir配置项指定了xhprof生成的分析报告保存的目录,要求此目录具有可写权限(不管PHP CLI,还是做为Web Server方式运行)

注意:php -m查看扩展是否加载

安装Graphviz

将XHProf的分析报告以程序的函数调用图来展现

1
2
3
4
5
6
7
8
9
$>wget http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.34.0.tar.gz

$>tar zxvf graphviz-2.34.0.tar.gz

$>cd graphviz-2.34.0

$>./configure

$>make && make install

如加上—prefix编译参数,请将安装完毕的主目录中的bin目录路径加入到环境变量PATH中,另外需要注意的如果通过XHProf提供的PHP UI界面查看函数调用图,需要将PHP的proc_open类的函数打开。

关于XHProf的更详细的介绍

http://web.archive.org/web/20110514095512/http://mirror.facebook.net/facebook/xhprof/doc.html

使用XHProf之前需要明白的概念

总表格报告(Flat profile):展示了总的函数调用级别的信息,包括Inclusive和Exclusive的执行时间、CUP计算时间、内存开销。

子表格报告:展示了单个函数明细的调用开销,包含
1)当前函数(current functions)所调用的函数(child functions)、调用当前函数(parent functions)的函数列表
2)某个函数调用某些特定函数及调用的次数
3)被调用函数(child functions)在调用函数(current functions)的总时间消耗所占时间比例

差异报告:有可能要比较运行多次的XHProf报告(如不同版本代码之间的执行情况,为了评价不同算法下的程序性能)。

合并报告:是指多次的XHProf报告融合为一个,主要是用于求平均值,分析程序的整体运行情况。

函数调用图:XHProf的分析报告以程序的执行流程图来展现,调用图能够突出显示程序的关键路径。

伪函数:XHProf跟踪include, include_once, require and require_once等操作语句,将其当做函数来进行处理,此类操作在Function Name列显示为load:: ,如:load::Application/Bootstrap.php,代表incloude文件Application/Bootstrap.php处理的开销情况。

递归调用:函数名()@,代表递归调用,其中n代表递归调用的深度。

XHProf Zend 扩展提供的PHP函数介绍

1)xhprof_enable
函数原型:void xhprof_enable ([ int $flags = 0 [, array $options ]] )
功能:启动 xhprof 性能分析器
参数:$flags可选标识,由XHProf扩展定义,XHPROF_FLAGS_NO_BUILTINS 使得跳过所有内置(内部)函数,XHPROF_FLAGS_CPU使输出的性能数据中添加 CPU 数据,XHPROF_FLAGS_MEMORY使输出的性能数据中添加内存数据,多个标识可通过位运算进行组合;$options array类型的可选选项,就是通过传递 ‘ignored_functions’ 选项来忽略性能分析中的某些函数。
返回值:无
说明:在开始分析代码时调用此函数

2)xhprof_disable
函数原型:array xhprof_disable ( void )
功能:停止 xhprof 分析器
参数:无
返回值:本次运行的 array 类型的 xhprof 数据
说明:在结束分析代码时调用此函数

3)xhprof_sample_enable
函数原型:void xhprof_sample_enable ( void )
功能:以采样模式启动 XHProf 性能分析
参数:无
返回值:无
说明:xhprof_enable() 的更轻量的版本,以采样模式开始性能分析。 抽样的间隔为 0.1 秒,样本记录了完整的函数调用堆栈。 主要使用的情况是以较低的性能开销来进行性能监控和诊断。

4)xhprof_sample_disable
函数原型:array xhprof_sample_disable ( void )
功能:停止 xhprof 性能采样分析器
参数:无
返回值:本次运行的xhprof采样数据,array 类型
说明:暂无

XHProf UI介绍

XHProf UI是PHP实现的,用于查看XHProf分析报告,分为两个部分xhprof_html和xhprof_lib。

xhprof_html包含三个PHP文件,

1)index.php: 展示单个xhprof分析报告表或者多个xhprof报告差异表

2)callgraph.php:将XHProf的分析报告以程序的函数调用图来展现(使用Graphviz)

3)typeahead.php: 响应AJAX请求函数获取子表格报告地址(可以忽略)

xhprof_lib目录包含生成单个xhprof报告表格、或者差异报告表格、函数调用图用到的类。

另外关于也有XHProf GUI的另一个分支:https://github.com/preinheimer/xhprof

访问XHProf UI

1)单个XHProf报告

1
http://<xhprof-ui-address>/index.php?run=<run_id>&source=<namespace>

其中run_id是在每次进行性能分析时都会分配的ID,由XHProfRuns_Default::save_run返回,也可以自定义run_id;source是指命名空间,只用于报告分类。

2)差异报告

1
http://<xhprof-ui-address>/index.php?run1=<run_id1>&run2=<run_id2>&source=<namespace>

其中run1和run2分别为对应的run_id(经测试只能两个报告的差异报告)

3)合并报告

1
http://<xhprof-ui-address>/index.php?run=<run_id1,run_id2,run_id3>&source=<namespace>

4)带权重的合并报告

1
http://<xhprof-ui-address>/index.php?run=<run_id1,run_id2,run_id3>&wts=20,30,50&source=<namespace>

使用XHProf示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?php
xhprof_enable(XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);

function splitElem(&$a, $low, $high)
{

$split_elem = $a[$low];

for(;;) {
while ($low < $high && $a[$high] >= $split_elem)
$high--;
if ($low >= $high) break;
$a[$low++] = $a[$high];

while ($low < $high && $a[$low] <= $split_elem)
$low++;
if ($low >= $high) break;
$a[$high--] = $a[$low];
}

$a[$low] = $split_elem;

return $high;
}

function quickSort(&$a, $low, $high)
{

if ($low >= $high || empty($a)) return;

$split_elem_index = splitElem($a, $low, $high);
quickSort($a, $low, $split_elem_index - 1);
quickSort($a, $split_elem_index+1, $high);
}

$a = array();

for ($i = 0; $i < 30; $i++) {
$a[] = rand(125, 250);
}

quickSort($a, 0, count($a) - 1);

$xhprof_data = xhprof_disable();

$XHPROF_ROOT = "/Library/WebServer/Documents";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";

$xhprof_runs = new XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_testing");

echo "http://localhost/xhprof_html/index.php?run={$run_id}&source=xhprof_testing/n";

?>

注意:的访问路径

xhprof报告示例

PHP性能分析工具xhprof介绍、安装、使用说明

XHProf报告字段含义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
Function Name:方法名称。

Calls:方法被调用的次数。

Calls%:方法调用次数在同级方法总数调用次数中所占的百分比。

Incl.Wall Time(microsec):方法执行花费的时间,包括子方法的执行时间。(单位:微秒)

IWall%:方法执行花费的时间百分比。

Excl. Wall Time(microsec):方法本身执行花费的时间,不包括子方法的执行时间。(单位:微秒)

EWall%:方法本身执行花费的时间百分比。

Incl. CPU(microsecs):方法执行花费的CPU时间,包括子方法的执行时间。(单位:微秒)

ICpu%:方法执行花费的CPU时间百分比。

Excl. CPU(microsec):方法本身执行花费的CPU时间,不包括子方法的执行时间。(单位:微秒)

ECPU%:方法本身执行花费的CPU时间百分比。

Incl.MemUse(bytes):方法执行占用的内存,包括子方法执行占用的内存。(单位:字节)

IMemUse%:方法执行占用的内存百分比。

Excl.MemUse(bytes):方法本身执行占用的内存,不包括子方法执行占用的内存。(单位:字节)

EMemUse%:方法本身执行占用的内存百分比。

Incl.PeakMemUse(bytes)Incl.MemUse峰值。(单位:字节)

IPeakMemUse%:Incl.MemUse峰值百分比。

Excl.PeakMemUse(bytes)Excl.MemUse峰值。单位:(字节)

EPeakMemUse%:Excl.MemUse峰值百分比。

使用XHProf的注意

对于应该不应该将XHProf部署到生产环境,我还不知晓,但是官方说可以,但是最好是采样模式进行尝试,以降低服务器资源开销。我使用xhprof也只是在开发环境。

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据

Go