《让php扩展开拓编程前路》 之 性能分析利器 xhprof | php 技术论坛-380玩彩网官网入口
- title: 《让php扩展开拓编程前路》 之 性能分析利器
xhprof
- tag:
pecl
、php
、profiler
、xhprof
、性能分析
- author: tacks
- create-date: 2023-05-16
- update-date: 2023-05-18
ref
- wiki
- pecl
- php
- php
- php
- github
- github
- github
- github
- github
- github
- github
- github
- github
- github
- blog @facebook
- packagist
- blog
1、intro
1.1 xhprof
的发展
php 扩展
xhprof
是一个轻量级的分层性能测量分析器,最开始由facebook/xhprof
代码转到 仓库维护。后来基于xhprof
分支。从pecl
上可以看到 扩展,不过中途也是有更换开发者,2013 年最新版到 是由 仓库维护,当时主要是php5.x
系列,随着php7.x
系列的更新,php底层数据类型实现进行优化,之前xhprof
版本无法在php7.x
上运行,于是更换成 ,截至目前 2023年05月xhprof
最新版本是 。还好后继有人,xhprof
依然活跃,可谓是xhprof
的第二世!第三世其实是tideways_xhprof
,当然本文暂且先不讨论tideways
相关扩展。
xhprof
扩展 是 php 的函数级层次分析器,具有简单的基于 html 的可视化界面。原始数据收集组件是用 c 语言实现的(作为 php 扩展)。性能分析展示层全部使用 php。它能够报告函数级包含和独占的挂起时间、内存使用情况、cpu 时间和每个函数的调用次数,以及整个的函数调用图。
当然 xhprof
有很多衍生的版本项目,虽然他们名字可能一样,但可能不是同一套代码,因此建议直接去看 github 上的代码。
本文讨论的 xhprof
扩展来源如下
pecl
上github
上
1.2 什么是 profiler
分析器 ?
profiler
分析器是一种用于监控并优化程序性能的工具,它可以找出应用程序中的性能瓶颈,从而帮助开发人员提高程序的响应速度和性能。
通常来说,它可以收集程序执行期间的各种指标和性能数据,包括但不限于,cpu使用率、内存使用情况、函数执行时间等,然后生成详细的性能分析报告,以及可视化的图表展示。
- 工具选择
- php 中,比如有
xdebug
、xhprof
、tideways
- 其他语言,如 go 中,比如
pprof
、dlv
、go-torch
等
- php 中,比如有
- 工具集成
- 应用程序执行
- 工具收集数据
- 可视化报告展示
- 函数调用频次
- 函数调用关系、调用链
- 函数执行耗时
- 函数内存消耗
- 火焰图
flame graph
- 堆栈图
call graph
- …
2、prepare
2.1 我的环境
php 7.3.20
没有是最新的是因为我太懒,晚点换
[root@centos7 ~]# php -v
php 7.3.20 (cli) (built: jan 11 2021 17:21:40) ( nts )
380玩彩网官网入口 copyright (c) 1997-2018 the php group
zend engine v3.3.20, 380玩彩网官网入口 copyright (c) 1998-2018 zend technologies
with zend opcache v7.3.20, 380玩彩网官网入口 copyright (c) 1999-2018, by zend technologies
[root@centos7 ~]# /php/php73/bin/pecl -v
pear version: 1.10.12
php version: 7.3.20
zend engine version: 3.3.20
running on: linux centos7 3.10.0-1160.11.1.el7.x86_64 #1 smp fri dec 18 16:34:56 utc 2020 x86_64
[root@centos7 ~]# cat /etc/redhat-release
centos linux release 7.9.2009 (core)
2.2 安装 xhprof
扩展
- pecl 安装
xhprof
- 如果是针对 php5.x 的,需要安装
xhprof-0.9.4
版本 - 如果是针对 php7.0 以上,则直接安装
xhprof
也就是最新版
- 如果是针对 php5.x 的,需要安装
[root@centos7 ~]# /php/php73/bin/pecl install xhprof
....
build process completed successfully
installing '/php/php7.3.20/lib/php/extensions/no-debug-non-zts-20180731/xhprof.so'
install ok: channel://pecl.php.net/xhprof-2.3.9
configuration option "php_ini" is not set to php.ini location
you should add "extension=xhprof.so" to php.ini
- 配置
php.ini
增加xhprof
配置xhprof.output_dir
# 创建目录
[root@centos7 ~]# mkdir -p /tmp/php-xhprof/output
# 追加配置
[root@centos7 ~]# vim /php/php7.3.20/lib/php.ini
[xhprof]
extension=xhprof.so
xhprof.output_dir=/tmp/php-xhprof/output
# 重启
[root@centos7 ~]# /etc/init.d/php-fpm73 restart
gracefully shutting down php-fpm . done
starting php-fpm done
- 检查
xhprof
是否被加载
[root@centos7 ~]# php73 -m | grep xhprof
xhprof
[root@centos7 ~]# php --ri
xhprof
xhprof support => enabled
version => 2.3.9
directive => local value => master value
xhprof.output_dir => /tmp/php-xhprof/output => /tmp/php-xhprof/output
xhprof.collect_additional_info => 0 => 0
xhprof.sampling_interval => 100000 => 100000
xhprof.sampling_depth => 2147483647 => 2147483647
2.3 其他准备
# 为防止需要图片相关依赖
[root@centos7 ~]# yum install libpng -y
[root@centos7 ~]# yum install graphviz -y
# 为性能数据采集准备
[root@centos7 php-xhprof]# php -m | grep -e "mongodb|xhprof"
mongodb
xhprof
3、ues profiler
3.1 xhprof
相关函数说明
- $flags 配置
xhprof_flags_no_builtins
跳过所有内置函数xhprof_flags_cpu
输出的性能数据中添加 cpu 数据xhprof_flags_memory
输出的性能数据中添加内存数据
- $options
- 忽略性能分析中的某些函数
- $flags 配置
- 返回值就是本次采集的 xhprof_data 数据
3.2 在 cli
中使用 xhprof
进行性能分析
3.2.1 引入 longxinh/xhprof
一些类库
- 创建一个项目目录
/code/php-xhprof
- 拉取 代码
- 创建一个测试目录
/code/php-xhprof/testcli
- 复制
longxinh/xhprof
代码目录中的xhprof_html
xhprof_lib
代码目录到testcli
[root@centos7 ~]# mkdir -p /code/php-xhprof
[root@centos7 ~]# mkdir -p /code/php-xhprof/testcli
[root@centos7 ~]# cd /code/php-xhprof
[root@centos7 php-xhprof]# git clone https://github.com/longxinh/xhprof
[root@centos7 php-xhprof]# cd /code/php-xhprof/testcli
[root@centos7 testcli]# cp -r /code/php-xhprof/xhprof/xhprof_* /code/php-xhprof/
3.2.2 在 testcli
目录下创建测试脚本 test.php
[root@centos7 testcli]# touch /code/php-xhprof/testcli/test.php
[root@centos7 php-xhprof]# tree -l 2
.
├── testcli
│ ├── inject.php
│ └── test.php
├── xhprof
│ ├── bin
│ ├── changelog
│ ├── credits
│ ├── examples
│ ├── extension
│ ├── license
│ ├── package.xml
│ ├── readme.md
│ ├── resource
│ ├── scripts
│ ├── support
│ ├── travis
│ ├── xhprof_html
│ └── xhprof_lib
├── xhprof_html
│ ├── callgraph.php
│ ├── css
│ ├── docs
│ ├── index.php
│ ├── jquery
│ ├── js
│ └── typeahead.php
└── xhprof_lib
├── display
└── utils
3.2.3 编写测试脚本 test.php
// 开启 xhprof
xhprof_enable(xhprof_flags_no_builtins xhprof_flags_cpu xhprof_flags_memory);
function test($i) {
if($i == 0) {
return 1;
} else {
return $i * test($i - 1);
}
};
$res = test(3);
var_dump($res); // 函数执行结果
// 结束 xhprof
$xhprof_data = xhprof_disable();
var_dump($xhprof_data); // xhprof 收集到的数据
// 下面与 xhprof 扩展无关,而是 php 序列化 xhprof_data 的数据,并生成一个文件
// 将收集到的数据 序列化存储到 xhprof.output_dir 目录中,生成一个唯一的文件,返回 文件 run_id
$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";
$xhprof_runs = new xhprofruns_default();
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_testcli");
var_dump($run_id);
3.2.4 执行测试脚本 test.php
[root@centos7 php]# php test.php
int(6)
array(5) {
["test@2==>test@3"]=>
array(5) {
["ct"]=>
int(1)
["wt"]=>
int(2)
["cpu"]=>
int(11)
["mu"]=>
int(832)
["pmu"]=>
int(0)
}
["test@1==>test@2"]=>
array(5) {
["ct"]=>
int(1)
["wt"]=>
int(13)
["cpu"]=>
int(13)
["mu"]=>
int(1408)
["pmu"]=>
int(0)
}
["test==>test@1"]=>
array(5) {
["ct"]=>
int(1)
["wt"]=>
int(16)
["cpu"]=>
int(16)
["mu"]=>
int(1984)
["pmu"]=>
int(0)
}
["main()==>test"]=>
array(5) {
["ct"]=>
int(1)
["wt"]=>
int(26)
["cpu"]=>
int(27)
["mu"]=>
int(2560)
["pmu"]=>
int(0)
}
["main()"]=>
array(5) {
["ct"]=>
int(1)
["wt"]=>
int(69)
["cpu"]=>
int(67)
["mu"]=>
int(3160)
["pmu"]=>
int(0)
}
}
string(13) "646329afc4f30"
3.2.5 查看 xhprof 收集的数据文件
[root@centos7 php]# cat /tmp/php-xhprof/output/646329afc4f30.xhprof_testcli.xhprof
a:5:{s:15:"test@2==>test@3";a:5:{s:2:"ct";i:1;s:2:"wt";i:2;s:3:"cpu";i:11;s:2:"mu";i:832;s:3:"pmu";i:0;}s:15:"test@1==>test@2";a:5:{s:2:"ct";i:1;s:2:"wt";i:13;s:3:"cpu";i:13;s:2:"mu";i:1408;s:3:"pmu";i:0;}s:13:"test==>test@1";a:5:{s:2:"ct";i:1;s:2:"wt";i:16;s:3:"cpu";i:16;s:2:"mu";i:1984;s:3:"pmu";i:0;}s:13:"main()==>test";a:5:{s:2:"ct";i:1;s:2:"wt";i:26;s:3:"cpu";i:27;s:2:"mu";i:2560;s:3:"pmu";i:0;}s:6:"main()";a:5:{s:2:"ct";i:1;s:2:"wt";i:69;s:3:"cpu";i:67;s:2:"mu";i:3160;s:3:"pmu";i:0;}}
3.2.6 xhprof_data 数据涵义
字段 | 涵义 |
---|---|
ct | 函数被调用的次数 |
wt | 函数的执行时间耗时 |
cpu | 函数消耗的cpu时间 |
mu | 函数方法使用的内存 |
pmu | 函数方法使用的峰值内存 |
3.2.6 查看 xhprof 可视化报告分析
只有数据没有图看起来很费劲,别忘记了,它有自带的可视化配置 html
nginx 配置 web ui ,然后重启 nginx, 可以访问
xhprof.tacks.com
server {
listen 80;
server_name xhprof.tacks.com;
# 配置 xhprof html 根目录
root /code/php-xhprof/xhprof_html/;
index index.html index.php;
access_log /logs/tacks/xhprof.tacks.com-access.log;
error_log /logs/tacks/xhprof.tacks.com-error.log;
rewrite_log on;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
fastcgi_param server_software nginx;
include fastcgi_params;
}
}
- 针对本例,应该访问
http://xhprof.tacks.com/index.php?run=646329afc4f30&source=xhprof_testcli
字段 | 涵义 |
---|---|
function name | 函数名 |
calls | 调用次数 |
incl. wall time (microsec) | 函数运行时间(包括子函数) |
iwall% | 函数运行时间(包括子函数)占比 |
excl. wall time (microsec) | 函数运行时间(不包括子函数) |
ewall% | 函数运行时间(不包括子函数)占比 |
[view full callgraph] | 函数调用链图 (需要graphviz) |
- 具体展示图表可以看本文 4.1 章节
3.2.7 分析所有 php 脚本文件
- 编写
xhprof
通用采集脚本inject.php
# /code/php-xhprof/testcli/inject.php
$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";
xhprof_enable(xhprof_flags_no_builtins xhprof_flags_cpu xhprof_flags_memory);
// 注册一个函数,当程序执行结束的时候去执行它。
register_shutdown_function(function () {
// stop profiler
$xhprof_data = xhprof_disable();
// 冲刷
if (function_exists('fastcgi_finish_request')) {
fastcgi_finish_request();
}
// 生成文件
$xhprof_runs = new xhprofruns_default();
$xhprof_runs->save_run($xhprof_data, "xhprof_testcli_inject");
});
- 在执行任意 php 脚本前,进行注入采集脚本,修改
php.ini
配置,设置auto_prepend_file
,然后重启 php
这样所有的 php 脚本文件执行都会自动注入 inject.php
采集文件,非常方便,无需入侵真正的 php 业务代码;
[root@centos7 php-xhprof]# vim /php/php73/lib/php.ini
; automatically add files before php document.
; http://php.net/auto-prepend-file
; auto_prepend_file =
auto_prepend_file=/code/php-xhprof/testcli/inject.php
3.3 在 php-fpm
中使用 xhprof
进行性能分析
3.3.1 分析特定域名的 web 请求
还是利用之前的 xhprof
通用采集脚本 inject.php
,可以创建一个新的 /code/php-xhprof/testfpm/inject.php
- 针对某个站点 利用
fastcgi_param
指令设置auto_prepend_file
- 问题:由于
php-fpm
进程可能会复用,也就是多个网站用到同一个php-fpm
worker
进程来处理,这种情况就有可能收集到其他网站的请求 - 解决:可以通过入侵方式,将代码写入到网站的入口文件,来进行收集数据;
- 问题:由于
# 追加 配置
# fastcgi_param php_value "auto_prepend_file=/code/php-xhprof/testfpm/inject.php";
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
fastcgi_param server_software nginx;
fastcgi_param php_value "auto_prepend_file=/code/php-xhprof/testfpm/inject.php";
include fastcgi.conf;
}
4、web-ui
4.1 使用 xhprof 自带页面进行性能数据的可视化
4.1.1 xhprof web ui 基本使用
可以看到采集的各种请求
- 点击某个
function name
查看 父子函数的数据对比- 可以进入查看 父函数(current function) 和 子函数(child functions) 的数据采集
- 点击
view callgraph
- 可以进入查看 函数的调用链,并且根据颜色可以看到哪个函数耗时最大
4.1.2 使用 diff report 对比两次请求采集的数据
tips 使用参数 run1 run2 分别指向两次请求的 run_id ,另外可以点击页面的 invert diff report 来反转两次请求的 run_id
- 请求 a
function test() {
$result = 0;
for ($i=1; $i <= 10000; $i) {
$result = $i;
}
return $result;
}
- 请求 b
function test() {
return 10000 * (110000) / 2;
}
请求b 相比 请求a 可以看到 cpu 和 内存 都大幅度降低;
可以看到函数调用耗时之差,以及调用次数之差
4.1.3 查看汇总请求
tips 使用参数 run=xxx,yyy,zzz 可以汇总多次请求
4.2 使用第三方工具进行性能数据的可视化
4.2.1 perftools/php-profiler
和 perftools/xhgui
的组合拳,瞬间搭建专属的性能分析平台
前情提要
- 性能分析利器
xhprof
- php 安装此扩展
- 通用采集分析器
profiler
perftools/php-profiler
- 支持多种性能分析的扩展;类似一个通用的黑盒,使用此组件,然后选择响应的 性能采集扩展即可
xhprof
对应的就是 类perftools/php-profiler/src/profilers/xhprof.php
- 支持采集数据的持久化;
- 性能可视化分析ui
xhgui
perftools/xhgui
- 将数据持久化到
mongodb
整体流程就是 project => php-profiler => xhprof => xhgui
快速起一个 web 项目
可以找任意框架,或者你当前的项目,这里只是为了演示,用了这个仓库 。
[root@centos7 php-xhprof]# pwd
/code/php-xhprof
# 克隆项目
[root@centos7 php-xhprof]# git clone https://github.com/tacks9/php-framework-by-composer pfc
[root@centos7 php-xhprof]# ls pfc/
app bootstrap.php composer.json composer.lock composer.phar config data public readme.md services vendor
# 配置 nginx
[root@centos7 php-xhprof]# vim /etc/nginx/conf/pfc.conf
server
{
listen 80;
server_name pfc.tacks.com;
index index.html index.htm index.php index.shtml index.shtm;
root /code/php-xhprof/pfc/public;
access_log /logs/tacks/pfc.tacks.com-access.log;
error_log /logs/tacks/pfc.tacks.com-error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
fastcgi_param server_software nginx;
include fastcgi_params;
}
}
# 重启 nginx
[root@centos7 php-xhprof]# systemctl restart nginx
# 设置 hosts
[root@centos7 php-xhprof]# vim /etc/hosts
127.0.0.1 pfc.tacks.com
# 模拟请求
[root@centos7 php-xhprof]# curl http://pfc.tacks.com/home/echotest
<h1> 控制器、方法 home/echotest </h1>
在你的项目引入
[root@centos7 pfc]# pwd
/code/php-xhprof/pfc
# composer 引入 perftools/php-profiler
[root@centos7 pfc]# composer require perftools/php-profiler
# 增加 profiler.php 探测器启动文件
[root@centos7 pfc]# touch config/profiler.php
# 项目入口文件引入 profiler.php
[root@centos7 pfc]# vim bootstrap.php
# 在自动加载器后面
// 【探测器】
require base_path.'/config/profiler.php';
- 探测器脚本
config/profiler.php
- 配置 profiler 使用的扩展为
xhprof
,因为本文主打就是xhprof
,当然如果你如果安装类似其他的扩展如tideways_xhprof
,可以自己尝试 - 配置数据存储方式
save.handler
- 主打通过
saver_stack
的方式,可以将采集数据以多种方式存储 - 接口上传
save.handler.upload
- 当然你可能会疑惑这个接口哪里来,当时看文档的时候愣是不知道哪里来的接口,这就需要组合拳的另一套
perftools/xhgui
工具
- 当然你可能会疑惑这个接口哪里来,当时看文档的时候愣是不知道哪里来的接口,这就需要组合拳的另一套
- 文件存储
save.handler.file
- 默认以 json 的方式存储到
/tmp/xhgui.data.jsonl
下
- 默认以 json 的方式存储到
- 主打通过
- 配置 profiler 使用的扩展为
// /code/php-xhprof/pfc/config/profiler.php
<?php
/**
* bootstrap for php-profiler. copy and customize this file,
* include this file inside some bootstrapper or other "early central point in execution"
*
* documentation:
* - https://github.com/perftools/php-profiler#create-profiler
* - https://github.com/perftools/php-profiler#config
*/
use xhgui\profiler\profiler;
use xhgui\profiler\profilingflags;
// require __dir__ . '/../vendor/perftools/php-profiler/autoload.php';
try {
$config = array(
// 选择性能分析器 xhprof 扩展
'profiler' => profiler::profiler_xhprof,
// 配置要捕获的分析数据
'profiler.flags' => array(
profilingflags::cpu,
profilingflags::memory,
profilingflags::no_builtins,
profilingflags::no_spans,
),
// 采集数据的保存方式
'save.handler' => profiler::saver_stack,
// 存储数据的接口
// https://github.com/perftools/php-profiler#upload-saver
'save.handler.upload' => array(
'url' => 'http://xhgui.tacks.com/run/import',
// 接口超时时间
'timeout' => 3,
// xhgui 的 upload.token
'token' => 'token',
),
// 存储数据的文件
// https://github.com/perftools/php-profiler#file-saver
'save.handler.file' => array(
'filename' => '/tmp/xhgui.data.jsonl',
),
// 采用堆栈的方式存储采集数据
// https://github.com/perftools/php-profiler#stack-saver
'save.handler.stack' => array(
'savers' => array(
profiler::saver_upload,
profiler::saver_file,
),
// 如果设置 true 就是全部存储,如果false,就按照顺序不成功就用下一个保存方式
'saveall' => false,
),
// 采用mongodb存储采集数据(作者不推荐直接存储到这里)
// https://github.com/perftools/php-profiler#mongodb-saver
'save.handler.mongodb' => array(
'dsn' => 'mongodb://127.0.0.1:27017',
'database' => 'xhprof',
// allows you to pass additional options like replicaset to mongoclient.
// 'username', 'password' and 'db' (where the user is added)
'options' => array(),
// allows you to pass driver options like ca_file to mongoclient
'driveroptions' => array(),
),
// environment variables to exclude from profiling data
'profiler.exclude-env' => array(),
'profiler.options' => array(),
// 探测器采集(可以保存一定比例的请求,而非全部)
// profile 1 in 100 requests.
// you can return true to profile every request.
'profiler.enable' => function () {
if ($_server['server_name'] == 'pfc.tacks.com') {
return true;
// 100%采样,默认为1%
return rand(1, 100) === 42;
} else {
return false;
}
},
// 请求 url 简化
'profiler.simple_url' => function ($url) {
return preg_replace('/=\d /', '', $url);
},
// 请求 url 替换,移除敏感信息,例如 token query
'profiler.replace_url' => function ($url) {
return str_replace('token', '', $url);
},
);
// 加载配置
$profiler = new profiler($config);
// 启动探测器
$profiler->start();
} catch (exception $e) {
error_log($e->getmessage());
}
你的php需要mongodb支持
[root@centos7 php-xhprof]# php --ri mongodb
mongodb
mongodb support => enabled
mongodb extension version => 1.15.2
mongodb extension stability => stable
libbson bundled version => 1.23.3
libmongoc bundled version => 1.23.3
libmongoc ssl => enabled
libmongoc ssl library => openssl
libmongoc crypto => enabled
libmongoc crypto library => libcrypto
libmongoc crypto system profile => disabled
libmongoc sasl => enabled
libmongoc icu => disabled
libmongoc compression => enabled
libmongoc compression snappy => disabled
libmongoc compression zlib => enabled
libmongoc compression zstd => disabled
libmongocrypt bundled version => 1.5.2
libmongocrypt crypto => enabled
libmongocrypt crypto library => libcrypto
crypt_shared library version => unknown
directive => local value => master value
mongodb.debug => no value => no value
采集数据持久化需要一个 mongodb
[root@centos7 php-xhprof]# ps -ef | grep mongo | grep -v "grep"
root 6666 1 1 may11 ? 01:30:17 /usr/bin/mongod --dbpath=/mongodb/data -f /etc/mongod.conf
[root@centos7 php-xhprof]# netstat -ntlp | grep mongod
tcp 0 0 0.0.0.0:27017 0.0.0.0:* listen 6666/mongod
启动一个
[root@centos7 php-xhprof]# pwd
/code/php-xhprof
# 克隆项目
[root@centos7 php-xhprof]# git clone https://github.com/perftools/xhgui
# 配置 nginx
[root@centos7 php-xhprof]# vim /etc/nginx/conf/xhgui.conf
server
{
listen 80;
server_name xhgui.tacks.com;
index index.html index.htm index.php index.shtml index.shtm;
root /code/php-xhprof/xhgui/webroot;
access_log /logs/tacks/xhgui.tacks.com-access.log;
error_log /logs/tacks/xhgui.tacks.com-error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
fastcgi_param server_software nginx;
include fastcgi_params;
}
}
# 重启 nginx
[root@centos7 php-xhprof]# systemctl restart nginx
- 浏览器访问
- 访问
- 你会发现 method not allowed ,这个就是我们在
php-profiler
中填写的配置save.handler.upload
,用来上传数据
- 你会发现 method not allowed ,这个就是我们在
大功告成,可以请求你的网站,然后使用性能分析xhgui
工具
多次请求
- 点击 method 列,例如 某一行的 get
- 点击 jump to functions
- 点击 view callgraph,查看本次请求的方法调用图
- 点击 compare this run,对比两次请求
- …
4.2.2 xhgui
的汉化版 laynefyc/xhgui-branch
,更贴合国人使用习惯
- 更多说明,请看
readme
- 更多说明,请看
前情提要
- 性能分析利器
xhprof
- php 安装此扩展
- 通用采集分析器
xhgui-chinese
- 支持采集数据的持久化,默认存储
mongodb
- 支持采集数据的持久化,默认存储
- 性能可视化分析ui
xhgui-chinese
的webroot
- 将数据可视化展示,并且进行汉化,看起来直观一些
整体流程就是 project => xhgui-chinese => mongodb => webroot
快速起一个 web 项目
可以找任意框架,或者你当前的项目,这里只是为了演示,依然用了这个仓库 。
- 初始化一个新的 web 项目即可,比如访问的
pfc.tacks.com
,剩下的就不演示了。
[root@centos7 php-xhprof]# git clone https://github.com/tacks9/php-framework-by-composer pfc
[root@centos7 pfc]# pwd
/code/php-xhprof/pfc
[root@centos7 pfc]# ls
app bootstrap.php composer.json composer.lock composer.phar config data public readme.md services vendor
部署 xhgui
汉化版
# 克隆项目
[root@centos7 php-xhprof]# git clone https://github.com/laynefyc/xhgui-branch xhgui-chinese
[root@centos7 xhgui-chinese]# pwd
/code/php-xhprof/xhgui-chinese
# composer 安装依赖
[root@centos7 xhgui-chinese]# composer install
# 设置缓存目录
[root@centos7 xhgui-chinese]# chmod -r 777 cache
[root@centos7 xhgui-chinese]# ls
cache code_of_conduct.md composer.json composer.lock config _config.yml external install.php license phpunit.xml readme.md src tests vendor webroot
# 配置 nginx
[root@centos7 xhgui-chinese]# vim /etc/nginx/conf/xhgui-chinese.conf
server
{
listen 80;
server_name xhgui-chinese.tacks.com;
index index.html index.htm index.php index.shtml index.shtm;
root /code/php-xhprof/xhgui-chinese/webroot;
access_log /logs/tacks/xhgui-chinese.tacks.com-access.log;
error_log /logs/tacks/xhgui-chinese.tacks.com-error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
fastcgi_param server_software nginx;
include fastcgi_params;
}
}
# 重启 nginx
[root@centos7 xhgui-chinese]# systemctl restart nginx
- 浏览器访问
设置 xhgui
汉化版的配置文件
# 自定义配置
[root@centos7 xhgui-chinese]# cp conf/config.default.php conf/config.php
[root@centos7 xhgui-chinese]# vim conf/config.php
conf/config.php
配置如下- 主要是对
profiler.enable
进行设置,只接收来自设定的域名请求 extension
扩展,依然采用xhprof
save.handler
采集数据,使用mongodb
,所以请先安装 php 的mongodb
扩展db.host
需要mongodb
的服务端,可以本地启动一个,账号密码啥的可以在db.options
设置在数组中- 数据库,默认采用
xhprof
,当然可以重设一下,比如xhprof-xhgui-chinese
- 主要是对
return array(
'debug' => false,
'mode' => 'development',
/*
* support extension: uprofiler, tideways_xhprof, tideways, xhprof
* default: xhprof
*/
'extension' => 'xhprof',
// can be either mongodb or file.
/*
'save.handler' => 'file',
'save.handler.filename' => dirname(__dir__) . '/cache/' . 'xhgui.data.' . microtime(true) . '_' . substr(md5($url), 0, 6),
*/
'save.handler' => 'mongodb',
// needed for file save handler. beware of file locking. you can adujst this file path
// to reduce locking problems (eg uniqid, time ...)
//'save.handler.filename' => __dir__.'/../data/xhgui_'.date('ymd').'.dat',
'db.host' => 'mongodb://127.0.0.1:27017',
'db.db' => 'xhprof-xhgui-chinese',
// allows you to pass additional options like replicaset to mongoclient.
// 'username', 'password' and 'db' (where the user is added)
'db.options' => array(),
'templates.path' => dirname(__dir__) . '/src/templates',
'date.format' => 'y-m-d h:i:s',
'detail.count' => 6,
'page.limit' => 25,
// profile 1 in 100 requests.
// you can return true to profile every request.
'profiler.enable' => function () {
// return true;//rand(1, 100) === 42;
if ($_server['server_name'] == 'pfc.tacks.com') {
return true;
// 100%采样,默认为1%
return rand(1, 100) === 42;
} else {
return false;
}
},
'profiler.simple_url' => function ($url) {
return preg_replace('/\=\d /', '', $url);
},
'profiler.filter_path' => array(
//'/home/admin/www/xhgui/webroot','f:/phppro'
)
);
对 mongodb
优化索引
这里用我本地测试的 mongodb
进行设置,如果你没有 mongodb
请先移步寻找如何安装。
至于 db 名字,看你在项目中如何配置的,如果为 xhprof-xhgui-chinese
就 use xhprof-xhgui-chinese
,默认的 db 名字为 xhprof
[root@centos7 pfc]# mongo
mongodb shell version v4.2.23
connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiservicename=mongodb
implicit session: session { "id" : uuid("7b8bf1d3-507b-4c2f-aa18-c1c4615b515f") }
mongodb server version: 4.2.23
> use xhprof-xhgui-chinese
> db.results.ensureindex( { 'meta.server.request_time' : -1 } )
> db.results.ensureindex( { 'profile.main().wt' : -1 } )
> db.results.ensureindex( { 'profile.main().mu' : -1 } )
> db.results.ensureindex( { 'profile.main().cpu' : -1 } )
> db.results.ensureindex( { 'meta.url' : 1 } )
设置 xhgui
需要监控的项目
header.php
需要引入的文件
[root@centos7 xhgui-chinese]# ls external/header.php
external/header.php
[root@centos7 xhgui-chinese]# ls /code/php-xhprof/xhgui-chinese/external/header.php
/code/php-xhprof/xhgui-chinese/external/header.php
nginx
配置,利用fastcgi_param
设置auto_prepend_file
# 配置 nginx
[root@centos7 php-xhprof]# vim /etc/nginx/conf/pfc.conf
server
{
listen 80;
server_name pfc.tacks.com;
index index.html index.htm index.php index.shtml index.shtm;
root /code/php-xhprof/pfc/public;
access_log /logs/tacks/pfc.tacks.com-access.log;
error_log /logs/tacks/pfc.tacks.com-error.log;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param script_filename $document_root$fastcgi_script_name;
fastcgi_param server_software nginx;
fastcgi_param php_value "auto_prepend_file=/code/php-xhprof/xhgui-chinese/external/header.php";
include fastcgi_params;
}
}
# 重启 nginx
[root@centos7 php-xhprof]# systemctl restart nginx
大功告成,可以请求你的网站,然后使用性能分析xhgui-chinese
工具
多次请求
- 点击 “方法” 列,例如 某一行的 get
- 点击 “跳转函数” 按钮
- 点击 “查看调用图” 按钮
- 点击 “查看火焰图” 按钮
- 点击 “对比这次运行” 按钮
- …
本作品采用《cc 协议》,转载必须注明作者和本文链接
tacks
太好了,非常需要这个
得侵入式代码,感觉不大方便