原文来自于:http://avnpc.com/pages/profiler-php-performance-online-by-xhprofjavascript
原创做者:AlloVincephp
以前一直使用基于Xdebug进行PHP的性能分析,对于本地开发环境来讲是够用了,但若是是线上环境的话,xdebug消耗较大,配置也不够灵活,所以线上环境建议使用xhprof进行PHP性能追踪及分析。html
xhprof是Facebook开源的轻量级PHP性能分析工具,Linux环境下能够经过pecl直接安装,好比在Ubuntu下仅需3行指令java
pecl install xhprof-beta
echo "extension=xhprof.so" > /etc/php5/fpm/conf.d/xhprof.ini
service php5-fpm restart
以后能够经过phpinfo()
检查扩展是否已经加载。mysql
具体如何使用呢,xhprof项目中已经提供了示例以及简易的UI,下载xhprof项目到web服务器,假设能够经过http://localhost/xhprof/
访问,那么访问http://localhost/xhprof/examples/sample.php
能够看到一些输出,而且提示经过访问http://<xhprof-ui-address>/index.php?run=XXX&source=xhprof_foo
查看结果。接下来访问http://localhost/xhprof/xhprof_html/
就能够看到已经保存的结果,列出了全部函数的调用以及所消耗的时间。git
分析一下示例代码sample.php
,关键部分只有2行:github
//开启xhprof并开始记录 xhprof_enable(); //运行一些函数 foo(); //中止记录并取到结果 $xhprof_data = xhprof_disable();
$xhprof_data
中记录了程序单步运行过程当中全部的函数调用时间及CPU内存消耗等,具体记录哪些指标能够经过xhprof_enable
的入口参数控制,以后的处理已经与xhprof扩展无关,大体是编写了一个存储类XHProfRuns_Default
,将$xhprof_data
序列化并保存到某个目录,能够经过XHProfRuns_Default(__DIR__)
将结果输出到当前目录,若是不指定则会读取php.ini配置文件中的xhprof.output_dir
,仍然没有指定则会输出到/tmp
。web
xhprof_html/index.php
将记录的结果整理并可视化,默认的UI里列出了:sql
每一项应该不难理解,以项目自带的sample.php
为例,示例中编写了一个main()
函数,main()
函数中调用foo()
、bar()
等一些子函数进行了一点字符处理。整个程序运行过程当中,main()
函数只运行了一次,而且因为main()
函数中包括了全部的逻辑,因此main()
函数的IWall%占比为100%,可是因为main()
函数的功能都是由子函数实现的,所以main()
函数的EWall%只有0.3%,而foo()
函数完成了主要的工做,EWall%有98.1%。所以在分析更大型的程序时,每每须要根据这几项指标分别排序,从不一样的角度审视性能消耗。mongodb
在xhprof_html/index.php
中还能够看到[View Full Callgraph]
连接,点击后能够绘制出一张可视化的性能分析图,若是点击后报错的话,多是缺乏依赖graphviz
,ubuntu能够经过apt安装
apt-get install graphviz
了解了上面这些,其实就已经能够将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数据以及展现数据的UI,听起来彷佛又是一大堆工做,有现成的轮子能够用吗?
通过搜索和比较,貌似比较好的选择有xhprof.io以及xhpgui。
两个项目作得事情差很少,都提供了xhprof数据保存功能以及一套索引展现数据的UI,下面是一些比较
xhprof.io
xhgui
能够看到其实两个项目都不够完善,相对而言xhgui不支持域名索引对于线上调试来讲是没法忍受的,所以我最后的选择是使用xhprof.io,可是本身进行了微量的调整,修改后的xhprof.io修正版支持:
安装及配置方法以下,假设web服务器根目录为/opt/htdocs
cd /opt/htdocs
git clone https://github.com/EvaEngine/xhprof.io.git cd xhprof.io/ composer install cp xhprof/includes/config.inc.sample.php xhprof/includes/config.inc.php vi xhprof/includes/config.inc.php
在MySQL中创建xhprof.io数据库,假设数据库名为xhprof
,而后导入xhprof/setup/database.sql
配置文件config.inc.php
中须要调整
'url_base' => 'http://localhost/xhprof.io/',
这是xhprof.io界面所在路径'pdo' => new PDO('mysql:dbname=xhprof;host=localhost;charset=utf8', 'root', 'password'),
根据MySQL实际状况调整配置enable
这是一个匿名函数,当匿名函数返回true时启用xhprof数据收集经过配置enable
项,就能够实现线上调试的需求,好比
始终开启xhprof
'enable' => function() { return true; }
1/100几率随机开启xhprof
'enable' => function() { return rand(0, 100) === 1; }
网页携带参数debug=1时开启xhprof
'enable' => function() { return !empty($_GET['debug']); }
网页URL为特定路径时开启
'enable' => function() { return strpos($_SERVER['REQUEST_URI'], '/testurl') === 0; }
最后按上文所述,在要配置的项目中包含xhprof.io/inc/inject.php
便可。
线上环境操做时务必要胆大心细,若是没有结果尤为注意须要检查xhprof扩展是否安装。
apt-get install mongodb php5-mongo php5-mcrypt
cp /etc/php5/mods-available/mcrypt.ini /etc/php5/fpm/conf.d/
cp /etc/php5/mods-available/mcrypt.ini /etc/php5/cli/conf.d/
cd /opt/htdocs
git clone https://github.com/perftools/xhgui.git cd xhgui composer install cp config/config.default.php config/config.php chown www-data.www-data -R cache
编辑Nginx配置文件加入
fastcgi_param PHP_VALUE "auto_prepend_file=/opt/htdocs/xhgui/external/header.php";
收集数据过多时能够清空mongodb
mongo
use xhprof; db.dropDatabase();