Linux系统下使用XHProf和XHGui分析PHP运行性能


Posted in PHP onDecember 08, 2015

什么是性能分析?
性能分析是衡量应用程序在代码级别的相对性能。性能分析将捕捉的事件包括:CPU的使用,内存的使用,函数的调用时长和次数,以及调用图。性能分析的行为也会影响应用性能。
什么时候应该进行性能分析?
在考虑是否进行性能分析时,你首先要想:应用是否存在性能问题?如果有,你要进一步考虑:这个问题有多大?

如果你不这样做,将会陷入一个陷阱——过早优化,这可能会浪费你的时间。

为了评断应用是否存在性能问题,你应该确定性能目标。例如,100 个并发用户的响应时间小于 1s 。然后,你需要进行基准测试,看是否达到这个目标。一个常见的错误是,在开发环境进行基准测试。事实上,你必须在生产环境进行基准测试。(实际生产环境或模拟的生产环境,后者很容易在 SaaS 实现。
用于基准测试的产品很多,包括 ab,siege 和 JMeter。我个人比较喜欢 JMeter 的功能集,但 ab 和 siege 更加易用。

一旦你确定应用存在性能问题,就需要分析其性能,实施改进,然后再一次进行基准测试,查看问题是否解决。每一次变更之后,你都该进行基准测试查看效果。如果你做了很多变更,却发现应用性能有所下降,你就无法确定具体是哪一次变更导致了这个问题。

下图是我定义的性能生命周期:

Linux系统下使用XHProf和XHGui分析PHP运行性能

性能下降的一般原因
导致性能下降的一般原因中,有些相当出人意料。即便是像 PHP 这样的高级语言,代码的好坏也很少是问题的根源。在当今的硬件配置条件下,CPU 很少是性能限制的原因。常见的原因反而是:

数据存储

  • PostgreSQL
  • MySQL
  • Oracle
  • MSSQL
  • MongoDB
  • Riak
  • Cassandra
  • Memcache
  • CouchDB
  • Redis

外部资源

  • APIs
  • 文件系统
  • 网络接口
  • 外部流程
  • 糟糕的代码

选择哪一种性能分析器?
在 PHP 世界里,有两个截然不同的的性能分析器——主动和被动。

主动 VS 被动性能分析
主动分析器在开发过程中使用,由开发人员启用。主动分析器收集的信息比被动分析器多,对性能的影响更大。通常,主动分析器不能用在生产环境中。XDebug 就是一种主动分析器。

因为无法在生产环境中使用主动分析器,Facebook 推出了一个被动分析器——XHProf。XHProf 是为了在生产环境中使用而打造的。它对性能的影响最小,同时收集足够的信息用于诊断性能问题。XHProf 和 OneAPM 都是被动分析器。

通常,XDebug 收集的额外信息对于一般的性能问题分析并不必要。这意味着,被动分析器是用于不间断性能分析的更佳选择,即使是在开发环境中。

XHProf + XHGui
XHProf 由 Facebook 开发的,包含一个基本的用户界面用于查看性能数据。此外,Paul Reinheimer 开发了 XHGui 和一个增强的用户界面(UI)用于查看、比较和分析性能数据。

安装
安装 XHProf
XHProf 可通过 PECL 安装,步骤如下:

$ pecl install xhprof-beta

该 pecl 命令将尝试自动更新你的 php.ini 设置。pecl 尝试更新的文件可以使用以下命令找到:

$ pecl config-get php_ini

它会在指定的文件(如果有的话)顶部增加新的配置行。你可能想把他们移到一个更合适的位置。

一旦你编译了该扩展程序,您必须启用它。为此,您需要在 PHP INI 文件添加以下代码:

[xhprof]
extension=xhprof.so

之后,结合 XHGui 就能轻松地执行性能分析与检查。

安装 XHGui
安装 XHGui,必须直接从 git 获取。该项目可以在 github 上找到,地址为:https://github.com/perftools/xhgui

XHGui 要求:

  • PHP 5.3+
  • ext/mongo
  • composer
  • MongoDB (若只需要收集数据,则可选可不选;若需要数据分析,则为必选)

首先,克隆项目到任意位置。在基于 Debian 的 Linux 系统(例如 Ubuntu 等等),可能是 /var/www。在 Mac OS X 系统,可能是 /Library/WebServer/Documents。

$ cd /var/www
$ git clone https://github.com/perftools/xhgui.git
$ cd xhgui
$ php install.php

最后一个命令是运行 composer 以安装依赖并检查 XHGui 缓存目录的权限。如果失败,你可以手动运行 composer install。

下一步,你可能需要创建配置文件。这一步很容易实现,可以使用在 /path/to/XHGui/config/config.default.php 下的默认配置文件。

如果你在本地运行 MongoDB,没有身份验证,则可能不需要这样做。因为它将回退为默认值。而在多服务器环境中,你会需要一个所有服务器都能进行存储的远程 MongoDB 服务器,并进行恰当的配置。

为提高 MongoDB 的性能,你可以运行以下指令以添加索引:

$ mongo
> use xhprof
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 } )

其他配置
如果你不想在生产环境中安装 mongo ,或无法让 Web 服务器访问 mongo 服务器,您可以将性能分析数据保存在磁盘中,再导入到本地 MongoDB 供以后分析。

为此,请在 config.php 中进行以下修改:

<?php 
'save.handler' = 'file', 
'save.handler.filename' => '/path/to/xhgui/xhprof-' .uniqid("", true). '.dat', 
?>

改变文件中的 save.handler,然后取消批注 save.handler.filename ,为其赋一个恰当的值。

注意:默认每天只保存一个分析文件。

一旦分析数据的准备就绪,你就可以使用 XHGui 附带的脚本导入之:

$php /path/to/xhgui/external/import.php /path/to/file.dat

在此之后的步骤都相同。

运行 XHGui
XHGui 是以 PHP 为基础的 Web 应用程序,你可以以 /path/to/xhgui/webroot 为根文件,设置一个标准的虚拟主机。

或者,你可以简单地使用 PHP 5.4+ cli-server 例如:

$ cd /path/to/xhgui
$ php -S 0:8080 -t webroot/
这将使 XHGui 在所有网络接口都可通过 8080 端口进行通信。

运行性能分析器
运行分析器时,你需要在待分析的所有页面包含 external/header.php 脚本。为此,你可以在 PHP ini 文件设置 auto_prepend_file 。你既可以直接在公共 INI 文件进行设置,也可以限制到单一的虚拟主机。

对于 Apache 服务器,添加以下代码:

php_admin_value auto_prepend_file "/path/to/xhgui/external/header.php"

对于 Nginx 服务器,在服务器配置中添加以下代码:

fastcgi_param PHP_VALUE "auto_prepend_file=/path/to/xhgui/external/header.php";

如果您使用 PHP 5.4+ cli-server(PHP -S),则必须通过命令行标记进行设置:

$ php -S 0:8080 -dauto_prepend_file=/path/to/xhgui/external/header.php

默认情况下,分析器运行时只分析(大约) 1% 的请求。这是由以下 external/header.php 代码控制的:

<?php 
if (rand(0, 100) !== 42) { 
  return;
}
?>

如果你想分析每一个请求(例如,在开发阶段),你可以将这段代码注释掉。如果你想让分析 10% 的请求,你可以做如下改动:

<?php
if (rand(0, 10) !== 4) {
  return;
}
?>

这允许你对一小部分用户请求进行分析,而不过多影响单个用户或太多用户。

如果你想在性能分析时进行手动控制,你可以这样做:

<?php 
if (!isset($_REQUEST['A9v3XUsnKX3aEiNsUDZzV']) && !isset($_COOKIE['A9v3XUsnKX3aEiNsUDZzV'])) { 
 return;
} else {
 // Remove trace of the special variable from REQUEST_URI
 $_SERVER['REQUEST_URI'] = str_replace(array('?A9v3XUsnKX3aEiNsUDZzV', '&A9v3XUsnKX3aEiNsUDZzV'), '', $_SERVER['REQUEST_URI']);
 setcookie('A9v3XUsnKX3aEiNsUDZzV', 1);
}
if (isset($_REQUEST['no-A9v3XUsnKX3aEiNsUDZzV'])) { 
 setcookie('A9v3XUsnKX3aEiNsUDZzV', 0, time() - 86400);
 return;
}
?>

这段代码会检查一个随机命名的 GET/POST/COOKIE 变量(在此例中为:A9v3XUsnKX3aEiNsUDZzV),同时创建一个同名的 Cookie ,用于分析该请求的整个过程,例如:表单提交后的重定向,Ajax 请求等等。

此外,它允许一个名为 no-A9v3XUsnKX3aEiNsUDZzV 的 GET/POST 变量来删除 Cookie ,停止分析。

当然,我们欢迎大家尝试使用 OneAPM 来为您的 PHP 和 Java 应用做免费的性能分析。OneAPM 独有的探针能够深入到所有 PHP 和 Java 应用内部完成应用性能管理和监控,包括代码级别性能问题的可见性、性能瓶颈的快速识别与追溯、真实用户体验监控、服务器监控和端到端的应用性能管理。 OneAPM 可以追溯到性能表现差的 SQL 语句 Traces 记录、性能表现差的第三方 API、Web 服务、Cache 等等。

PHP 相关文章推荐
使用网络地址转换实现多服务器负载均衡
Oct 09 PHP
关于php连接mssql:pdo odbc sql server
Jul 20 PHP
调试一段PHP程序时遇到的三个问题
Jan 17 PHP
php模拟ping命令(php exec函数的使用方法)
Oct 25 PHP
php计算几分钟前、几小时前、几天前的几个函数、类分享
Apr 09 PHP
如何让thinkphp在模型中自动完成session赋值小教程
Sep 05 PHP
wordpress安装过程中遇到中文乱码的处理方法
Apr 21 PHP
PHP SPL标准库之数据结构堆(SplHeap)简单使用实例
May 12 PHP
WordPress中用于创建以及获取侧边栏的PHP函数讲解
Dec 29 PHP
Yii框架中用response保存cookie,用request读取cookie的原理解析
Sep 04 PHP
php使用redis的几种常见操作方式和用法示例
Feb 20 PHP
PHP程序守护进程化实现方法详解
Jul 16 PHP
thinkPHP中create方法与令牌验证实例浅析
Dec 08 #PHP
详解PHP的Yii框架中日志的相关配置及使用
Dec 08 #PHP
UPUPW 更新 64 位 Apache 系列 PHP 7.0 正式版
Dec 08 #PHP
学习php设计模式 php实现模板方法模式
Dec 08 #PHP
PHP7正式版测试,性能惊艳!
Dec 08 #PHP
学习php设计模式 php实现命令模式(command)
Dec 08 #PHP
学习php设计模式 php实现合成模式(composite)
Dec 08 #PHP
You might like
mac下Apache + MySql + PHP搭建网站开发环境
2014/06/02 PHP
php字符串函数学习之strstr()
2015/03/27 PHP
PHP中each与list用法分析
2016/01/08 PHP
PHP使用preg_split()分割特殊字符(元字符等)的方法分析
2017/02/04 PHP
php实现的中秋博饼游戏之掷骰子并输出结果功能详解
2017/11/06 PHP
css3实现背景模糊的三种方式
2021/03/09 HTML / CSS
用jQuery技术实现Tab页界面之二
2009/09/21 Javascript
JavaScript?Apple设备检测示例代码
2013/11/15 Javascript
js获取select默认选中的Option并不是当前选中值
2014/05/07 Javascript
JavaScript使用function定义对象并调用的方法
2015/03/23 Javascript
jQuery幻灯片特效代码分享--鼠标滑过按钮时切换(2)
2020/11/18 Javascript
jQuery插件zTree实现获取当前选中节点在同级节点中序号的方法
2017/03/08 Javascript
karma+webpack搭建vue单元测试环境的方法示例
2018/05/24 Javascript
三分钟学会用ES7中的Async/Await进行异步编程
2018/06/14 Javascript
用vscode开发vue应用的方法步骤
2019/05/06 Javascript
JS中FileReader类实现文件上传及时预览功能
2020/03/27 Javascript
使用 Opentype.js 生成字体子集的实例代码详解
2020/05/25 Javascript
使用Python抓取模板之家的CSS模板
2015/03/16 Python
CentOS 6.5下安装Python 3.5.2(与Python2并存)
2017/06/05 Python
python通过百度地图API获取某地址的经纬度详解
2018/01/28 Python
python爬虫之自动登录与验证码识别
2020/06/15 Python
python 分离文件名和路径以及分离文件名和后缀的方法
2018/10/21 Python
使用PM2+nginx部署python项目的方法示例
2018/11/07 Python
Python Pandas 转换unix时间戳方式
2019/12/07 Python
python opencv图片编码为h264文件的实例
2019/12/12 Python
jupyter 导入csv文件方式
2020/04/21 Python
The Hut德国站点:时装、家居用品、美容等
2016/09/23 全球购物
美国指甲油品牌:Deco Miami
2017/01/30 全球购物
中国旅游网站:途牛旅游网
2019/09/29 全球购物
办公室文秘自我鉴定
2013/09/21 职场文书
企业标语口号
2014/06/10 职场文书
2016自主招生教师推荐信范文
2015/03/23 职场文书
2015年行风建设工作总结
2015/05/15 职场文书
2019年最新感恩节祝福语(28句)
2019/11/27 职场文书
Nginx搭建rtmp直播服务器实现代码
2021/03/31 Servers
如何理解Vue简单状态管理之store模式
2021/05/15 Vue.js