xhprof安装使用

安装:

到pecl官网下载xhprof的最新版:http://pecl.php.net/package/xhprof

wget http://pecl.php.net/get/xhprof-0.9.4.tgz
tar zxvf xhprof-0.9.4.tgz
cd xhprof-0.9.4
#拷贝这两个目录到一个可访问的host下
cp -r xhprof_html xhprof_lib /var/www/xhprof
cd extension which php-config #记录下php-config的路径,接下来要用。 phpize ./configure --with-php-config=/usr/bin/php-config #此处的地址就是上面你记录下来php-config的地址 make make install

修改php.ini

[xhprof]
extension=xhprof.so
;
;xhprof生成的文件存放路径。
;记得目录有可写权限,否则文件无法生成,xhprof也不报错,这个问题我犯了错误了。
;另外,这个目录不是要配置host访问的目录,host的目录还是xhprof_html,往下看就明白了
;xhprof.output_dir=<directory_for_storing_xhprof_runs>
;
xhprof.output_dir=/tmp

重启php-fpm就OK了,不过为了显示效果更炫,最好继续安装Graphviz。

安装Graphviz的目的是为了xhprof图形化web工具查看profiling log文件。

wget http://www.graphviz.org/pub/graphviz/stable/SOURCES/graphviz-2.24.0.tar.gz  
tar zxf graphviz-2.24.0.tar.gz  
cd graphviz-2.24.0  
./configure  
make  
make install 

使用:

// start profiling
xhprof_enable();
// run program // stop profiler
$xhprof_data = xhprof_disable(); // Saving the XHProf run // using the default implementation of iXHProfRuns. // $XHPROF_ROOT = "/var/www/xhprof";//需要include下边的两个文件,路径就是上边cp时写的路径 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(); // 保存运行结果在xhprof_foo下,类似命名空间 // **NOTE**: //save_run返回一个唯一的run_id,也可以通过参数自己指定id. $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");
//输出连接到页面,点击页面中的连接访问
echo "http://<xhprof-ui-address>/xhprof_html/index.php?run=$run_id&source=xhprof_foo\n".

 如此一来,会在上面设定的xhprof.output_dir目录里生成名字类似49bafaa3a3f66.xhprof_foo的数据文件。

可以很方便的通过Web方式浏览效果:

http://www.v.com/xhprof_html/index.php?run=49bafaa3a3f66&source=xhprof_foo

分析:

$xhprof_data中记录了程序单步运行过程中所有的函数调用时间及CPU内存消耗等,具体记录哪些指标可以通过xhprof_enable的入口参数控制,之后的处理已经与xhprof扩展无关,大致是编写了一个存储类XHProfRuns_Default,将$xhprof_data序列化并保存到某个目录,可以通过XHProfRuns_Default(__DIR__)将结果输出到当前目录,如果不指定则会读取php.ini配置文件中的xhprof.output_dir,仍然没有指定则会输出到/tmp

xhprof_html/index.php将记录的结果整理并可视化,默认的UI里列出了:

主要的:

Inclusive Time (或子树时间):包括子函数所有执行时间。
Exclusive Time/Self Time:函数执行本身花费的时间,不包括子树执行时间。
Wall时间:花去了的时间或挂钟时间。
CPU时间:用户耗的时间+内核耗的时间。

表格中的:

Function Name 函数名
Calls 调用次数
Calls% 调用百分比
Incl. Wall Time (microsec) 调用的包括子函数所有花费时间 以微秒算(一百万分之一秒)
IWall% 调用的包括子函数所有花费时间的百分比
Excl. Wall Time (microsec) 函数执行本身花费的时间,不包括子树执行时间,以微秒算(一百万分之一秒)
EWall% 函数执行本身花费的时间的百分比,不包括子树执行时间
Incl. CPU(microsecs) 调用的包括子函数所有花费的cpu时间。减Incl. Wall Time即为等待cpu的时间
ICpu% Incl. CPU(microsecs)的百分比
Excl. CPU(microsec) 函数执行本身花费的cpu时间,不包括子树执行时间,以微秒算(一百万分之一秒)。
ECPU% Excl. CPU(microsec)的百分比
Incl.MemUse(bytes) 包括子函数执行使用的内存。
IMemUse% Incl.MemUse(bytes)的百分比
Excl.MemUse(bytes) 函数执行本身内存,以字节算
EMemUse% Excl.MemUse(bytes)的百分比
Incl.PeakMemUse(bytes) Incl.MemUse的峰值
IPeakMemUse% Incl.PeakMemUse(bytes) 的峰值百分比
Excl.PeakMemUse(bytes) Excl.MemUse的峰值
EPeakMemUse% EMemUse% 峰值百分比

xhprof_html/index.php中还可以看到[View Full Callgraph]链接,点击后可以绘制出一张可视化的性能分析图,如果点击后报错的话,可能是缺少依赖graphviz

xhprof_enable()参数:
 
注意:默认情况下只有调用次数和占用时间是记录了的。您也可以选择同时记录CPU时间和/或单纯记录内存使用量。这样:
 
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); 

同时在分析时去掉内置函数:

xhprof_enable(XHPROF_FLAGS_NO_BUILTINS | XHPROF_FLAGS_CPU | XHPROF_FLAGS_MEMORY);

忽略指定的函数( 0.9.2或更高版本支持):

xhprof_enable(
  0,
    array('ignored_functions' =>  array('call_user_func',
                                        'call_user_func_array')));

同时记录内存:

xhprof_enable(    
    XHPROF_FLAGS_MEMORY,    
    array('ignored_functions' =>array(
                    'call_user_func',                    'call_user_func_array')
));

 

查看不同的XHProf用户界面:

PHP源码目录结构XHProf的用户界面的由PHP实现。代码存放在两个子目录中: xhprof_html/和xhprof_lib/ 。xhprof_html目录包含了3个顶级PHP页面。

index.php :查看一个单一运行或差异报告。

callgraph.php :以图片的形式查看一次XHProf运行的调用关系图。

typeahead.php :在XHProf的报告中被后台调用来进行函数的自动补全。

查看diff报告:

要查看命名空间<namespace>下runid分别是< run_id1>和<run_id2>的两个报告,访问URL:

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

汇总报告:

您也可以指定一组run id来汇总得到您想要的报告视图。

如果你有三个XHProf运行,都在"benchmark‘命名空间下,run id分别是1,2,3。要查看这些运行的汇总报告:

http://<xhprof-ui-address>/index.php?run=1,2,3&source=benchmark

加权汇总 :

进一步假设,上述3个运特分别对应三种程序,p1.php,p2.php和p3.php ,通常以20%,30%,50%概率混合:要查看汇总报告所对应的加权平均数这些运行使用:

http://<xhprof-ui-address>/index.php?run=1,2,3&wts=20,30,50&source=benchmark

 

取样分析(自己实现和xhprof实现):

不想每个请求都进行分析,自己通过随机数方式取样。

$randKey = mt_rand(1, 10000);    
if ($randKey == 1)
{
    xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
} 
  
// Test Code Start
   ……
 // Test Code End
    
if ($randKey == 1)
{
    $xhprofData = xhprof_disable();

    include_once "/data/zivn.me/xhprof_lib/utils/xhprof_lib.php";
    include_once "/data/zivn.me/xhprof_lib/utils/xhprof_runs.php";

    $xhprofRuns = new XHProfRuns_Default();
    $xhprofRuns->save_run($xhprofData, "xhprof");
}

Xhprof扩展还提供了一个轻量级采样模式 。采样间隔为0.1秒。采样记录了整个函数调用堆栈。如果想以增加极低的负载作代价来进行性能监控和诊断,采样模式就是你想要的。用xhprof_sample_enable()和xhprof_sample_disable()代替xhprof_enable()和xhprof_disable() 即可。

更好的注入方式:

理解了上边的配置和使用后,其实就已经可以将xhprof整合到任何我们已有的项目中去了。目前大部分MVC框架都有唯一的入口文件,只需要在入口文件的开始处注入xhprof的逻辑

//开启xhprof
xhprof_enable(XHPROF_FLAGS_MEMORY | XHPROF_FLAGS_CPU);
//在程序结束后收集数据
register_shutdown_function(function() {
    $xhprof_data = xhprof_disable();

    //让数据收集程序在后台运行
    if (function_exists('fastcgi_finish_request')) {
        fastcgi_finish_request();
    }

    //保存xhprof数据
    ...
});

但是这样免不了要修改项目的源代码,其实php本身就提供了更好的注入方式,比如将上述逻辑保存为/opt/inject.php,然后修改php fpm配置文件

vi /etc/php5/fpm/php.ini

修改auto_prepend_file配置:

auto_prepend_file = /opt/inject.php

这样所有的php-fpm请求的php文件前都会自动注入/opt/inject.php文件

如果使用Nginx的话,还可以通过Nginx的配置文件设置,这样侵入性更小,并且可以实现基于站点的注入。

fastcgi_param PHP_VALUE "auto_prepend_file=/opt/inject.php";

更好的分析工具:xhprof.io还是xhpgui:

注入代码后我们还需要实现保存xhprof数据以及展示数据的UI,听起来似乎又是一大堆工作,有现成的轮子可以用吗?

查看这个博客的介绍:http://avnpc.com/pages/profiler-php-performance-online-by-xhprof

 

posted @ 2015-09-06 12:29  leezhxing  阅读(619)  评论(0编辑  收藏  举报