xhprof介绍
XHProf是一个分层PHP性能分析工具。它报告函数级别的请求次数和各种指标,包括阻塞时间,CPU时间和内存使用情况。一个函数的开销,可细分成调用者和被调用者的开销,XHProf数据收集阶段,它记录调用次数的追踪和包容性的指标弧在动态callgraph的一个程序。它独有的数据计算的报告/后处理阶段。在数据收集时,XHProfd通过检测循环来处理递归的函数调用,并通过给递归调用中每个深度的调用一个有用的命名来避开死循环。XHProf分析报告有助于理解被执行的代码的结构,它有一个简单的HTML的用户界面( PHP写成的)。基于浏览器的性能分析用户界面能更容易查看,或是与同行们分享成果。也能绘制调用关系图。
安装接入xhprof
1.下载安装xhprof
wget https://pecl.php.net/get/xhprof-2.3.9.tgz
tar -zxvf xhprof-2.3.9.tgz
cd ./xhprof-2.3.9/extension
phpize
./configure --with-php-config=/usr/local/php-7.4/bin/php-config
make
make install
2. php.ini增加配置
[xhprof]
extension=xhprof.so;
xhprof.output_dir=/tmp/xhprof; #产生文件目录####其中 xhprof.output_dir 是 xhprof 的输出目录,每次执行 xhprof 的 save_run 方法时都会生成一个 run_id.project_name.xhprof 文件。这个目录在哪里并不重要。注意此路径的权限要可读写!!否则文件无法生成成功
需要配置下 php.ini 的 error.log
- 新建xhprof 的输出目录
mkdir /tmp/xhprof
chmod -R 777 /tmp/xhprof
- 将xhprof相关文件复制到项目目录中
### index.php增加内容,同级目录下新建一个xhprof目录,xhprof-2.3.9目录下xhprof_html,xhprof_lib移动至xhprof目录下。
cp -rp /root/xhprof-2.3.9/xhprof_html /home/wwwroot/xxx项目目录/xhprof/
cp -rp /root/xhprof-2.3.9/xhprof_lib /home/wwwroot/xxx项目目录/xhprof/
chmod -R 777 /home/wwwroot/xxx项目目录/xhprof/
用参数调用 /login?xhprof
login
脚本接入
<?php
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS +
XHPROF_FLAGS_CPU +
XHPROF_FLAGS_MEMORY);register_shutdown_function(function(){
$data = xhprof_disable(); //返回运行数据
//xhprof_lib 在下载的包里存在这个目录,记得将目录包含到运行的php代码中
include_once 'xhprof/xhprof_lib/utils/xhprof_lib.php';
include_once 'xhprof/xhprof_lib/utils/xhprof_runs.php';
$objXhprofRun = new XHProfRuns_Default();
$objXhprofRun->save_run($data, "xhprof"); //test 表示文件后缀
});
xhprof使用
本地环境:http://127.0.0.1:8801/xhprof/xhprof_html/
4. 性能指标的具体含义、主要注意哪些参数
```go
A、表格分析时,需要注意的指标funciton name : 函数名
calls: 调用次数
Incl. Wall Time (microsec): 函数运行时间(包括子函数) 单位微秒
IWall%:函数运行时间(包括子函数)占比
Excl. Wall Time(microsec):函数运行时间(不包括子函数) 单位微秒
EWall%:函数运行时间(不包括子函数)B、图形分析时,需要注意的地方红框是消耗资源占用比例最高的地方,需要着重看,根据具体数值,选择性进行优化。黄色是消耗资源占用比例稍高的地方,根据具体数值,选择性优化。白色是消耗资源占用比例一般的地方,基本不需要处理,不过也要根据具体数值分析。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 访问域名: nginx配置:
server {
listen 443;
server_name wcxhprof-work.woczx.com;
index index.html index.htm index.php;
root /home/wwwroot/work/woc3-api/common/xhprof/xhprof_html;
#ssl on;
ssl_certificate /usr/local/nginx/conf/vhosts/crt/woczx.com.pem;
ssl_certificate_key /usr/local/nginx/conf/vhosts/crt/woczx.com.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
location ~ .php {
#fastcgi
#fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
include fastcgi.conf;
#pathinfo
set $path_info "";
set $real_script_name $fastcgi_script_name;
if ($fastcgi_script_name ~ "^(.+?\.php)(/.+)$") {
set $real_script_name $1;
set $path_info $2;
}
#fastcgi conf
fastcgi_param SCRIPT_FILENAME $document_root$real_script_name;
fastcgi_param SCRIPT_NAME $real_script_name;
fastcgi_param PATH_INFO $path_info;
}
location ^~ /.git
{
deny all;
}
error_log /home/logs/nginx//xhprof-woc3-error.log; location =/robots.txt {
default_type text/html;
add_header Contest-Type "text/plain; charset=UTF-8";
return 200 "User-Agent: *\nDisallow: /";
}
}
表格分析:
图形分析:
安装和使用中遇到的问题解决办法
1.访问xhprof点击[View Full Callgraph]查看报错failed to execute cmd: " dot -Tpng"
原因一:未安装graphviz
如果看到 sh: dot: command not found ,说明服务器上没有安装画图软件graphviz
yum安装: yum install graphviz
原因二:php.ini设置了禁用proc_open方法
如果安装好了graphviz,仍然出现”failed to execute cmd”,检查下服务器上的php.ini中disable_functions这项是不是限制了proc_open,因为在xhprof_lib/utils/callgraph_utils.php的xhprof_generate_image_by_dot中使用了proc_open函数,
YII框架接入:
1.common/main.php 引入 xhprof 组件
namespace common\bootstraps;use Yii;
use yii\base\BootstrapInterface;
use yii\base\Event;
use yii\web\Response;/**
* xhprof分析
*/
class Xhprof implements BootstrapInterface
{
public function bootstrap($app)
{
if (PHP_SAPI === 'cli') {
$this->adapterCli($app);
} else {
$this->adapterFpm($app);
}
} /**
* 适配CLI
*/
public function adapterCli($app): void
{
//CLI 唯一标识
$uniqueName = './yii ';
if (isset($app->request->params[0])) {
$uniqueName .= $app->request->params[0];
} //相同的脚本一分钟只记录一次
$key = 'xhprof_cli:' . md5($uniqueName);
if ($app->cache->get($key)) {
return;
} //守护进程不记录
if (isDaemon()) {
return;
} register_shutdown_function(function () use ($app) {
$data = xhprof_disable(); include_once Yii::getAlias('@common') . '/xhprof/xhprof_lib/utils/xhprof_lib.php';
include_once Yii::getAlias('@common') . '/xhprof/xhprof_lib/utils/xhprof_runs.php'; $objXhprofRun = new \XHProfRuns_Default();
$app->zipKin->setTag('xhprof.id', $objXhprofRun->save_run($data, 'cli'));
});
$app->cache->set($key, 1, 60);
} /**
* 适配FPM
*/
public function adapterFpm($app): void
{
//加上特定标识的接口走xhprof分析
if (!isset($_GET['__xhprof'])) {
return;
} Event::on(Response::class, Response::EVENT_AFTER_SEND, static function () use ($app) {
$data = xhprof_disable(); include_once Yii::getAlias('@common') . '/xhprof/xhprof_lib/utils/xhprof_lib.php';
include_once Yii::getAlias('@common') . '/xhprof/xhprof_lib/utils/xhprof_runs.php'; $objXhprofRun = new \XHProfRuns_Default();
$app->zipKin->setTag('xhprof.id', $objXhprofRun->save_run($data, 'fpm'));
});
}
}
2. 修改yii 文件 【console 的入口文件】
#!/usr/bin/env php
/**
* Yii console bootstrap file. */
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');if (!isset($_SERVER['IS_DAEMON'])) {
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS + XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
}require __DIR__ . '/vendor/autoload.php';
require __DIR__ . '/vendor/yiisoft/yii2/Yii.php';
require __DIR__ . '/common/config/bootstrap.php';
require __DIR__ . '/console/config/bootstrap.php';$config = yii\helpers\ArrayHelper::merge(
require __DIR__ . '/common/config/main.php',
require __DIR__ . '/common/config/main-local.php',
require __DIR__ . '/console/config/main.php',
require __DIR__ . '/console/config/main-local.php'
);$application = new yii\console\Application($config);
$exitCode = $application->run();
exit($exitCode);
忽略守护进程 supervisord
supervisord 加了个环境变量 IS_DAEMON
/**
* 是否守护进程
*/
function isDaemon(): bool
{
return isset($_SERVER['IS_DAEMON']);
}
3. 修改各模块的 index.php
defined('YII_DEBUG') or define('YII_DEBUG', true);
defined('YII_ENV') or define('YII_ENV', 'dev');//加上特定标识的接口走xhprof分析
if (isset($_GET['__xhprof'])) {
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS + XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
}require __DIR__ . '/../../vendor/autoload.php';
require __DIR__ . '/../../vendor/yiisoft/yii2/Yii.php';
require __DIR__ . '/../../common/config/bootstrap.php';
require __DIR__ . '/../config/bootstrap.php';$config = yii\helpers\ArrayHelper::merge(
require __DIR__ . '/../../common/config/main.php',
require __DIR__ . '/../../common/config/main-local.php',
require __DIR__ . '/../config/main.php',
require __DIR__ . '/../config/main-local.php'
);(new yii\web\Application($config))->run();
4.定期清理xhprof生成的文件
1 0 * * * find /tmp/xhprof/ -mtime +5 -name "*.xhprof" -delete;
发表评论 取消回复