一、安装xhprof
wget http://pecl.php.net/get/xhprof-0.9.4.tgz tar -zxvf xhprof-0.9.4.tgz cd xhprof-0.9.4/extension/ phpize ./configure --with-php-config=/usr/local/php/bin/php-config make && make install
二、配置PHP.ini
[xhprof] extension=xhprof.so; ; directory used by default implementation of the iXHProfRuns ; interface (namely, the XHProfRuns_Default class) for storing ; XHProf runs. ; ;xhprof.output_dir=<directory_for_storing_xhprof_runs> xhprof.output_dir=/tmp/xhprof
三、测试
server php-fpm restart yum install -y graphviz cp examples xhprof_html xhprof_lib /data/www/xhprof/ -R
测试代码如下
<?php function bar($x) { if ($x > 0) { bar($x - 1); } } function foo() { for ($idx = 0; $idx < 5; $idx++) { bar($idx); $x = strlen("abc"); } } // start profiling xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY); // run program foo(); // stop profiler $xhprof_data = xhprof_disable(); // display raw xhprof data for the profiler run print_r($xhprof_data); $XHPROF_ROOT = realpath(dirname(__FILE__) .'/..'); include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php"; include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php"; // save raw data for this profiler run using default // implementation of iXHProfRuns. $xhprof_runs = new XHProfRuns_Default(); // save the run under a namespace "xhprof_foo" $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo"); echo "---------------\n". "Assuming you have set up the http based UI for \n". "XHProf at some address, you can view run at \n". "http://<xhprof-ui-address>/index.php?run=$run_id&source=xhprof_foo\n". "---------------\n";
然后在浏览器中运行
Array ( [foo==>bar] => Array ( [ct] => 5 [wt] => 557 [cpu] => 0 [mu] => 2668 [pmu] => 0 ) [foo==>strlen] => Array ( [ct] => 5 [wt] => 124 [cpu] => 1000 [mu] => 404 [pmu] => 0 ) [bar==>bar@1] => Array ( [ct] => 4 [wt] => 204 [cpu] => 0 [mu] => 2068 [pmu] => 0 ) [bar@1==>bar@2] => Array ( [ct] => 3 [wt] => 97 [cpu] => 0 [mu] => 1516 [pmu] => 0 ) [bar@2==>bar@3] => Array ( [ct] => 2 [wt] => 41 [cpu] => 0 [mu] => 960 [pmu] => 0 ) [bar@3==>bar@4] => Array ( [ct] => 1 [wt] => 9 [cpu] => 0 [mu] => 404 [pmu] => 0 ) [main()==>foo] => Array ( [ct] => 1 [wt] => 1055 [cpu] => 1000 [mu] => 3796 [pmu] => 0 ) [main()==>xhprof_disable] => Array ( [ct] => 1 [wt] => 5 [cpu] => 0 [mu] => 412 [pmu] => 0 ) [main()] => Array ( [ct] => 1 [wt] => 1749 [cpu] => 1000 [mu] => 4952 [pmu] => 0 ) ) --------------- Assuming you have set up the http based UI for XHProf at some address, you can view run at http://<xhprof-ui-address>/index.php?run=55706da1eea18&source=xhprof_foo ---------------
生成图片:http://<xhprof-ui-address>/index.php?run=55706da1eea18&source=xhprof_foo
Inclusive Time (or Subtree Time): Includes time spent in the function as well as in descendant functions called from a given function. Exclusive Time/Self Time: Measures time spent in the function itself. Does not include time in descendant functions. Wall Time: a.k.a. Elapsed time or wall clock time. CPU Time: CPU time in user space + CPU time in kernel space Inclusive Time 包括子函数所有执行时间。 Exclusive Time/Self Time 函数执行本身花费的时间,不包括子树执行时间。 Wall Time 花去了的时间或挂钟时间。 CPU Time 用户耗的时间+内核耗的时间 Inclusive CPU 包括子函数一起所占用的CPU Exclusive CPU 函数自身所占用的CPU
点击[View Full Callgraph]
可以看到效率的图片
了解了上面这些,其实就已经可以将xhprof整合到任何我们已有的项目中去了
目前大部分MVC框架都有唯一的入口文件,只需要在入口文件的开始处注入xhprof的逻辑
<?php //开启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,听起来似乎又是一大堆工作,有现成的轮子可以用吗?
经过搜索和比较,貌似比较好的选择有xhprof.io以及xhpgui。
测试地址:https://dev.anuary.com/8d50658e-f8e0-5832-9e82-6b9e8aa940ac/?xhprof[template]=request&xhprof[query][request_id]=108151