xhprof 是 Facebook 09 年出的一个很优秀的 PHP profiler 工具,但 Facebook 后来迁移到 hhvm,早已不再维护,它在 PHP7 下有诸多 bug。
使用兼容的 xhprof 安装
xhprof 已经很久没有更新了,使用他人的repo1:
cd ~
git clone https://github.com/longxinH/xhprof
cd xhprof/extension/
查找 php7 下的 phpize 的位置。
which php71 # 查看 php71 的位置
ll /usr/bin/php71 # 查看软链接的位置
ls /opt/remi/php71/root/usr/bin/ # 查看所有命令
安装插件。
/opt/remi/php71/root/usr/bin/phpize
./configure --with-php-config=/opt/remi/php71/root/usr/bin/php-config --enable-xhprof
sudo make
sudo make install
重启 php-fpm。
sudo service php71-php-fpm restart
php71 -m | grep xhprof
此时,安装成功。我们配置一下 xhprof 插件:
[xhprof]
extension=xhprof.so;
xhprof.output_dir=/var/tmp/xhprof
其中 xhprof.output_dir 是 xhprof 的输出目录,每次执行 xhprof 的 save_run 方法时都会生成一个 run_id.project_name.xhprof 文件。这个目录在哪里并不重要。
nginx 配置访问
当生成 .xhprof 文件之后,我们就可以利用 xhprof_lib 来展示结果了。
创建文件夹 /var/www/html/xhprof,然后配置 nginx 如下2:
server {
listen 80;
root /var/www/html/xhprof/;
server_name your_host;
location = / {
index index.php;
}
location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
在 /var/www/html/xhprof/xhprof_html 下创建 index.php
<?php
echo phpinfo();
?>
访问 http://your_host/index.php 查看是否正确显示 phpinfo。
当配置成功之后,将 xhprof 中的 xhprof_lib 和 xhprof_html 两个文件夹复制到 /var/www/html/xhprof/ 下,然后访问 http://your_host/xhprof_html/index.php 即可。
PS:安装 yum install graphviz 查看图形界面。
修改 nginx 配置中的 root 直接指向 xhprof_html,配置如下:
server {
listen 80;
root /var/www/html/xhprof/xhprof_html;
server_name your_host;
location = / {
index index.php;
}
location ~ \.php {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
因为 xhprof_html 下已经有 index.php 了,所以可以直接访问 http://your_host。
# nginx 指向的路径
$ ls /var/www/html/xhprof
footer.php header.php index.php xhprof_html xhprof_lib
# xhprof 保存的数据
$ ls /var/tmp/xhprof
5979c9dfe223a.your_project.xhprof 597aae1684192.your_project.xhprof
使用方法
和之前一样,将要检查性能的代码包裹起来就可以了。
<?php
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
// 要检查性能的代码
$xhprof_data = xhprof_disable();
include_once '/var/www/html/xhprof/xhprof_lib/utils/xhprof_lib.php';
include_once '/var/www/html/xhprof/xhprof_lib/utils/xhprof_runs.php';
$xhprof_runs = new \XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, 'your_project');
当然这里也可以将前后的代码单独开一个php文件:header.php 和 footer.php。
// header.php
<?php
if (extension_loaded('xhprof')) {
include_once 'xhprof_lib/utils/xhprof_lib.php';
include_once 'xhprof_lib/utils/xhprof_runs.php';
xhprof_enable(XHPROF_FLAGS_CPU + XHPROF_FLAGS_MEMORY);
}
?>
// footer.php
<?php
if (extension_loaded('xhprof')) {
$profiler_namespace = 'your_project';
$xhprof_data = xhprof_disable();
$xhprof_runs = new XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, $profiler_namespace);
}
?>
然后用这两个文件包裹代码。如果是 Apache,可以在项目的 .htaccess 文件中添加:
#php_value auto_prepend_file /var/www/html/xhprof/header.php
#php_value auto_append_file /var/www/html/xhprof/footer.php
如果是 nginx + php-fpm,可以在php-fpm.d/www.conf 添加:
php_value[auto_prepend_file] = /var/www/html/xhprof/header.php
php_value[auto_append_file] = /var/www/html/xhprof/footer.php
个人还是更喜欢在需要的地方手动 require:
<?php
include_once '/var/www/html/xhprof/header.php';
// 要检查性能的代码
include_once '/var/www/html/xhprof/footer.php';
这样更加灵活,而且不会每个请求都生成一份报告,只在需要的时候生成。
Notice
- 如果遇到错误 failed to execute cmd: " dot -Tpng". stderr: ` (process:24220): Pango-WARNING **: Invalid UTF-8 string passed to pango_layout_set_text() '。暂时不清楚怎么解决,可以选择避开它。将 xhprof_lib/utils/callgraph_utils.php 的 121,122 行的打印和 exit 注释掉。
- 如果遇到错误 Error: either we can not find profile data for run_id xxx or the threshold 0.01 is too small or you do not have 'dot' image generation utility installed,无法生成 png 图片,可能是因为生成的文件中有不能识别的字符,修复如下3:
$cmd = " dot -T".$type; // 在 cmd 之后添加一个转码工作就可以了 $dot_script = iconv("UTF-8", "ASCII//IGNORE", $dot_script);
- 如果想要更好看的 UI,可以参考以下链接1,链接2,链接3 (手动搭免费)。
- 下面是一些参数说明
性能点 | 描述 |
---|---|
Inclusive Time | 包括子函数所有执行时间 |
Exclusive Time/Self Time | 函数执行本身花费的时间,不包括子树执行时间 |
Wall Time | 花去了的时间或挂钟时间 |
CPU Time | 用户耗的时间 + 内核耗的时间 |
Inclusive CPU | 包括子函数一起所占用的 CPU |
Exclusive CPU | 函数自身所占用的 CPU |
-
xhprof issue 和某博文提到了一些替代 repo,除此之外还有 tideways 等 ↩
-
nginx 的配置参考了 某 gitbook 和 nginx wiki ↩