利用PHP扩展Xhprof分析项目性能实践教程


Posted in PHP onSeptember 05, 2018

一、背景

项目即将上线,想通过一些工具来分析代码的稳定性和效率,想起在上个团队时使用过的xhprof扩展;因为换了新电脑,所以需要重新编译此扩展,现将安装与实际排查过程完整记录下来,方便自己回顾和帮助更多的读者。

XHProf 是 FaceBook 开发的一个函数级别的 PHP 分层分析器。

数据收集部分是一个基于 C 的 PHP 扩展,分析报告是一系列基于 PHP 的 HTML 导航页面。

XHProf 能统计每个函数的调用次数、内存使用、CPU占用等多项重要的数据。

并且 XHProf 还能比较两个统计样本,或从多个数据样本中汇总结果。

XHProf 是分析 PHP 程序执行效率的利器,能让我们得到更底层的的分析数据。

下面话不多说了,来一起看看详细的介绍吧

二、操作步骤

  • 安装扩展
  • 配置扩展
  • 测试分析

三、安装

xhprof扩展PHP并不自带,需要笔者去单独安装它,安装之后才能使用,笔者这里采用源码安装方式,安装过程如下

3.1 下载源码

xhprof在PHP的PECL官方上面已经比较老了,笔者的PHP版本为PHP7.1因此,需要在GitHub上下载xhprof上比较新的源码,参考命令如下

git clone https://github.com/longxinH/xhprof

3.2 检测环境

进入编译的文件夹,参考命令

cd xhprof/extension/

现在笔者需要编译一下源码,在编译之前可以使用phpze来探测PHP的环境,参考命令如下:

phpize

返回结果如下

Configuring for:
PHP Api Version:         20160303
Zend Module Api No:      20160303
Zend Extension Api No:   320160303

3.3 编译安装

生成 Makefile,为下一步的编译做准备

./configure

返回结果如下

creating libtool
appending configuration tag "CXX" to libtool
configure: creating ./config.status
config.status: creating config.h
config.status: config.h is unchanged

开始编译,并进行安装

make && make install

返回结果如下

Build complete.
Don't forget to run 'make test'.

Installing shared extensions:     /usr/local/Cellar/php@7.1/7.1.19/pecl/20160303/

从返回信息中可以看到已经安装完成,并显示了扩展文件存放的位置

四、配置

在编译安装源码之后,笔者还需要对PHP的配置文件夹以及xhprof的进行一些简单的配置,操作过程如下所示

4.1 找出配置文件位置

要修改PHP的配置首先需要知道配置文件在什么位置,这里可以通过PHP的命令来查看配置文件存放位置,参考命令如下:

php --ini

执行命令后,返回结果如下

Configuration File (php.ini) Path: /usr/local/etc/php/7.1
Loaded Configuration File:         /usr/local/etc/php/7.1/php.ini
Scan for additional .ini files in: /usr/local/etc/php/7.1/conf.d
Additional .ini files parsed:      /usr/local/etc/php/7.1/conf.d/ext-opcache.ini

在返回结果当中,可以看到多个配置文件的路径,笔者所需要的是第二个文件php.ini

查看扩展目录存放位置,参考命令如下

cat /usr/local/etc/php/7.1/php.ini | grep extension_dir

返回结果如下

extension_dir = "/usr/local/lib/php/pecl/20160303"
; extension_dir = "ext"
; Be sure to appropriately set the extension_dir directive.
;sqlite3.extension_dir =

4.2 修改配置

从返回的结果当中,可以看到扩展的存放目录位置如下

/usr/local/lib/php/pecl/20160303

现在需要将刚才编译好的xhprof扩展复制到该目录当中,参考命令如下

cp /usr/local/Cellar/php@7.1/7.1.19/pecl/20160303/xhprof.so /usr/local/Cellar/php@7.1/7.1.19/pecl/20160303/

通过vim编辑器编辑配置文件,参考命令如下

vim /usr/local/etc/php/7.1/php.ini

在配置文件尾部增加xhprof的配置,以及自定义一个用来保存xhprof生成的源文件参考配置如下

[xhprof]
extension=xhprof.so
xhprof.output_dir=/data/www/xhprof/save_output_dir

4.3 重启生效

保存好之后,笔者重启php-fpm让其配置生效,重启命令可以通过brew命令来查看,参考命令如下:

brew info php@7.1

在命令执行后,返回的信息中可以看到如下信息

To have launchd start php@7.1 now and restart at login:
 brew services start php@7.1
Or, if you don't want/need a background service you can just run:
 php-fpm

因此笔者构造的重启PHP-FPM命令如下:

brew services restart php@7.1

重启完成后,返回结果如下

Stopping `php@7.1`... (might take a while)
==> Successfully stopped `php@7.1` (label: homebrew.mxcl.php@7.1)
==> Successfully started `php@7.1` (label: homebrew.mxcl.php@7.1)

4.4 验证安装

现在验证xhprof扩展是否已经安装完成,参考命令如下

php -m | grep xhprof

命令执行后,安装扩展成功的返回结果将会显示xhprof,如下图所示

利用PHP扩展Xhprof分析项目性能实践教程

五、测试

经过上面的操作笔者已经成功的安装与配置,现在需要用PHP代码来进行验证xhprof的分析效果

5.1 创建虚拟主机

首先创建一个虚拟主机,让用户可以通过浏览器访问所访问,创建虚拟主机需要有一个根目录,并编辑nginx配置文件,具体操作如下:

5.1.1 创建项目目录

创建项目根目录,参考命令如下

mkdir -p /Users/song/mycode/work/test

创建成功之后,笔者需要将之前git拉下来的部分代码复制到项目根目录当中,参考命令如下

cp -r xhprof/xhprof_html /Users/song/mycode/work/test/
cp -r xhprof/xhprof_lib /Users/song/mycode/work/test/

5.1.2 编辑配置文件

添加配置文件,参考命令

/usr/local/etc/nginx/nginx.conf

添加配置文件如下

server {
  listen  80;
  server_name test.localhost;

  root /Users/song/mycode/work/test;
  index index.html index.htm index.php;
  
  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;
   include  fastcgi_params;
  }

 }

在/etc/hosts文件中增加入一行解析记录,记录内容如下:

127.0.0.1 test.localhost

5.2 新建测试代码

在git仓库的examples文件夹下,已经有了一份demo代码,不过这份代码的注释都是英文,而且排版方式也不易笔者自己理解,因此笔者重新编辑了此文件,参考步骤如下命令

使用vim新建一个PHP文件

vim /Users/song/mycode/work/test/test.php

在文件中加入以下代码

<?php

//加载所需文件
include_once "./xhprof_lib/utils/xhprof_lib.php";
include_once "./xhprof_lib/utils/xhprof_runs.php";

//随意定义一个函数
function test($max)
{
 for ($idx = 0; $idx < $max; $idx++) {
  echo '';
 }
}

//定义测试方法
function a()
{
 test(rand(1000,5000));
}

//开始分析
xhprof_enable();

//需要分析的函数
a();

//结束分析
$xhprof_data = xhprof_disable();
//实例化xhprof类
$xhprof_runs = new XHProfRuns_Default();
//获取当前当前页面分析结果
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");

echo "\nhttp://test.localhost/xhprof/xhprof_html/index.php?run=$run_id&source=xhprof_foo\n";

保存代码之后,通过浏览器访问对应的URL地址,URL地址如下所示

http://test.localhost/xhprof/test.php

5.3 结果分析

运行后结果,如下图

利用PHP扩展Xhprof分析项目性能实践教程

在页面中可以看到一个URL地址,复制并打开此URL地址之后,便能看到此代码的分析结果,如下图所示

利用PHP扩展Xhprof分析项目性能实践教程

在页面中有一个列表,展示了每一个方法所消耗的时间,如果觉得列表的方式表示不够清晰,点击页面中的 View Full Callgraph 链接可以直接生成一个图片,如下图所示

利用PHP扩展Xhprof分析项目性能实践教程

在图中很清晰的可以看到执行时间都消耗在test方法上,因此笔者可以针对这个方法进行针对性的优化。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
全文搜索和替换
Oct 09 PHP
用PHP和ACCESS写聊天室(十)
Oct 09 PHP
WINDOWS下php5.2.4+mysql6.0+apache2.2.4+ZendOptimizer-3.3.0配置
Mar 28 PHP
追求程序速度,而不是编程的速度
Apr 23 PHP
php 判断访客是否为搜索引擎蜘蛛的函数代码
Jul 29 PHP
PHP连接Access数据库的方法小结
Jun 20 PHP
zf框架db类的分页示例分享
Mar 14 PHP
WordPress中转义HTML与过滤链接的相关PHP函数使用解析
Dec 22 PHP
PHP如何将XML转成数组
Apr 04 PHP
3种方法轻松处理php开发中emoji表情的问题
Jul 18 PHP
Fleaphp常见函数功能与用法示例
Nov 15 PHP
php实现图片压缩处理
Sep 09 PHP
PHP时间处理类操作示例
Sep 05 #PHP
PHP命名空间与自动加载类详解
Sep 04 #PHP
ThinkPHP框架实现定时执行任务的两种方法分析
Sep 04 #PHP
php 后端实现JWT认证方法示例
Sep 04 #PHP
PHP利用Mysql锁解决高并发的方法
Sep 04 #PHP
TP5(thinkPHP5)框架基于ajax与后台数据交互操作简单示例
Sep 03 #PHP
PHP实现的AES双向加密解密功能示例【128位】
Sep 03 #PHP
You might like
PHP操作MongoDB GridFS 存储文件的详解
2013/06/20 PHP
php 使用file_get_contents读取大文件的方法
2014/11/13 PHP
Yii框架获取当前controlle和action对应id的方法
2014/12/03 PHP
php+mysqli实现批量执行插入、更新及删除数据的方法
2015/01/29 PHP
PHP判断表达式中括号是否匹配的简单实例
2016/10/22 PHP
Yii框架实现图片上传的方法详解
2017/05/20 PHP
微信公众平台开发教程⑥ 微信开发集成类的使用图文详解
2019/04/10 PHP
PHP页面静态化――纯静态与伪静态用法详解
2020/06/05 PHP
PHP如何通过date() 函数格式化显示时间
2020/11/13 PHP
学习从实践开始之jQuery插件开发 菜单插件开发
2012/05/03 Javascript
js变换显示图片的实例
2013/04/16 Javascript
JavaScript实现的GBK、UTF8字符串实际长度计算函数
2014/08/27 Javascript
jquery学习总结(超级详细)
2014/09/04 Javascript
JavaScript 作用域链解析
2014/11/13 Javascript
js实现进度条的方法
2015/02/13 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
jQuery EasyUI 布局之动态添加tabs标签页
2015/11/18 Javascript
jquery 判断selection range 是否在容器中的简单实例
2016/08/02 Javascript
Jquery Easyui日历组件Calender使用详解(23)
2016/12/18 Javascript
js实现显示手机号码效果
2017/03/09 Javascript
[02:26]DOTA2英雄米拉娜基础教程
2013/11/25 DOTA
详解Python的Django框架中inclusion_tag的使用
2015/07/21 Python
django基于存储在前端的token用户认证解析
2019/08/06 Python
Python greenlet和gevent使用代码示例解析
2020/04/01 Python
Python包和模块的分发详细介绍
2020/06/19 Python
python 多进程和协程配合使用写入数据
2020/10/30 Python
使用sublime text3搭建Python编辑环境的实现
2021/01/12 Python
Python plt 利用subplot 实现在一张画布同时画多张图
2021/02/26 Python
村庄绿化方案
2014/05/07 职场文书
小学生常见病防治方案
2014/06/06 职场文书
应届本科毕业生求职信
2014/07/23 职场文书
初中运动会前导词
2015/07/20 职场文书
患者身份识别制度
2015/08/06 职场文书
2015年评职称个人工作总结
2015/10/15 职场文书
英语教学课后反思
2016/02/15 职场文书
七年级上册生物的课件
2019/08/07 职场文书