使用XHGui来测试PHP性能的教程


Posted in PHP onJuly 03, 2015

Profiling是一项用来观察程序性能的技术,非常适用于发现程序的瓶颈或者紧张的资源。Profiling能够深入程序的内部,展现request处理过程中每一部分代码的性能;同时,也可以确定有问题的请求(request);对于有问题的请求,我们还可以确定性能问题发生在请求内部的位置。对于PHP,我们有多种Profiling工具,本文主要集中在——XHGui,一款非常优秀的工具。XHGui构建在XHProf之上(XHProf由Facebook发布),但是对于剖析结果增加了更好的存储,同时增加了更加良好的信息获取接口。从这方面来说,XHGui更像是一个全新的工具。

XHGui已经经历过几个版本的迭代,但当前版本提供了更加漂亮的用户界面,并且使用MongoDB存储其剖析结果。相比于前一版本来说,所有这些方面都是巨大的改进;因为,前一版本更像是开发者设计的,采用文件来保存数据,使得收集的数据非常难以使用。XHGui 2013是一个非常全面的Profiling工具,无论是对管理人员来说还是对于开发者;与此同时,XHGui 2013被设计的足够轻巧以便能够在生产环境下运行。

本文将一步一步演示程序的安装,同时向你展现使用该工具可以收集的各方面信息。

第一步:安装依赖

因为XHGui有一些依赖项,所以我们第一步就是解决这个问题。底下的所有的教程都是基于Ubuntu 13.04平台的,当然,你应该可以把它们改编下并适用到到你自己的平台上。目前而言,我们需要安装MongoDB, PHP,并有一些安装PECL拓展的能力。

首先,我们要安装MongoDB,这边有一些官方的安装教程,你可以找到和你系统相关的细节,但是现在我将通过简单的通过APT来安装:
 

aptitude install mongodb

通过这个方式获取的MongoDB的版本可能不是最新的,因为这个产品的更新速度真的很快。但是,如果你想让它保持一个很新的版本,你可以把MongoDB提供的库添加到你的包管理器里,这样你就能得到一个最新的了。

与此同时,我们还需要针对PHP的Mongo 驱动。在仓库中该驱动的版本有点老,为了今天的演示,我们将从Pecl中进行获取。如果你的机器上没有pecl命令,你可以通过下面的命令进行安装:
 

aptitude install php-pear

然后,我们通过下面的命令向PHP添加MongoDB的驱动程序:
 

pecl install mongo

为了完成安装,最后我们需要在php.ini文件中新增加一行。但是,新版本的Ubuntu为配置PHP扩展提供了一个新系统,该系统更像Apache模块安装——将所有的配置保存在一个地方,然后创建一个符号链接以启动配置。首先,我们创建一个文件来保存设置,尽管在本示例中仅需要在设置中新增一行以启动扩展。我们将其保存在文件/etc/php5/mods-available/mongo.ini,新增下面一行:
 

php5enmod mongo
再次使用pecl来安装xhprof扩展程序。该程序目前仅是beta版本,因此安装命令如下:

 
pecl install xhprof-beta

命令行会再一次提示我们在php.ini新增一行。我们采用与上面一样的方法,创建文件/etc/php5/mods-available/xhprof.ini,并在里面新增如下内如:
 

extension=xhprof.so
此时,我们可以检查一下这些模块是否正确安装——通过在命令行运行php -m命令。记住,不要忘记重启Apache,以便web接口能够启用这些扩展。

安装XHGui

XHGui本身主要由web页面组成,它为XHProf扩展收集的数据提供更加友好的界面。你可以从代码库GitHub repo克隆;也可以直接下载zip文件,然后进行解压缩。获取程序之后,确定缓存目录有足够的权限以便web服务器有权限写入文件。最后,运行安装脚本:
 

php install.php

这就是程序安装所需的一切,并且会自动安装一些依赖程序;如果发生异常,安装程序也会给你提示。

我更喜欢将XHGui安装在虚拟主机当中;这需要.htaccess文件允许,也需要启动RUL重写。启动URL重写表明需要启动mod_rewrite模块,通过下面的命令:
 

a2enmod rewrite

(不要忘记重启Apache)。如果一切顺利,你可以正常访问XHGui的URL并且可以看到如下内容:

使用XHGui来测试PHP性能的教程

 在虚拟主机中启动XHGui

此时,我们希望启动XHGui以便检验我们网站的性能。注意,性能测试最好在进行任何优化之前执行一次,以便检测优化的效果。最简单的方法是在虚拟主机中增加auto_prepend_file声明,如下图所示:

<VirtualHost *:80>
  ServerName example.local
 
  DocumentRoot /var/www/example/htdocs/
  php_admin_value auto_prepend_file /var/www/xhgui/external/header.php
 
  <Directory /var/www/example/htdocs/>
    Options FollowSymLinks Indexes
    AllowOverride All
  </Directory>
 
</VirtualHost>

一切就绪之后,你可以开始剖析网站的请求。XHGui只会剖析网站请求的1%,所以为了使XHGui获取有意义的数据,你需要让XHGui运行一段时间或者使用类似Apache Bench的测试工具批量提交一批请求。为什么在100个请求当中XHGui只会剖析一个?因为XHGui的设计初衷就是足够的轻巧以便在生产环境中使用,它不想对每一个请求产生额外的开销,1%的采样率已经能够为网站的总体流量提供较为清晰的概览。

满足数据

我使用测试虚拟机运行本文所有的示例,采用Joind.in API作为测试代码。为了产生一些流量,我将API测试案例运行了几遍。你也可以在一定负载的情况下收集数据,所以你可以在压力测试时使用XHGui,你甚至可以在上线站点中使用XHGui收集数据(听起来很疯狂,但是Facebook正式为了此应用才开发了该工具)。在向应用发送了一定的请求之后,重新访问XHGui,现在它就已经保存了一些数据:

使用XHGui来测试PHP性能的教程

该图向我们展示了XHGui为我们分析的每一个请求,最新的请求排在第一位,并且为每一个请求展示了一些额外信息。这些信息包括:

  •     URL:请求所访问的URL
  •     Time:请求发起时间
  •     wtor: "Wall Time" ?请求所经历的所有时间. 这是 "wall clock" time的简称,表示用户等待请求完成所有的时间
  •     cpu:花费在该请求上的CPU时间
  •     mu:该请求所消耗的内存
  •     pmu:请求处理过程中所消耗的最大内存

为了获取每一遍请求("run")更为详细的信息,你可以点击每一个请求你感兴趣的列。你可以点击URL以便获取该URL所有请求的详细信息。无论哪种方法,你都可以获取该请求更为详细的信息:

使用XHGui来测试PHP性能的教程

使用XHGui来测试PHP性能的教程

 这是一个非常长并且非常详细的页面,所以我引用了两个截图(如果展示所有的信息将需要5个截图)。上面一幅图的左边部分展示了该请求相关的一些信息,以便帮助你跟踪这些统计信息与哪些方面有关;右边的主要部分展示了最消耗时间的各部分以及在请求过程中每个函数调用所消耗的内存。在图的下方有一个主键以表明每一栏。

第二幅图展示了该请求每一个组成部分更为详细的信息。我们可以看到每一部分调用的次数以及时间消耗,还包括CPU和内存信息。无论是inclusive还是exclusive信息都做了详细的展示:exclusive表示仅仅是该方法调用所产生的消耗;inclusive不仅包括本函数所产生的消耗,还包括本函数调用的其他函数所产生的消耗。

XHGui另一个特性是“调用图”(Callgraph),“调用图”以生动的虚拟方式展示了时间是如何消耗的:

使用XHGui来测试PHP性能的教程

 这很好的展示了函数调用的层次。最好的一点是,该图是可交互的,你可以拖拽以更好的查看连接;你还可以用鼠标滑过“圆环”(blob)以查看更多的信息。当你与它交互时,他会很好玩的弹回和移动,这不是一个非常重要的特性但却让我感觉非常好玩。

理解数据

拥有大量的统计数据非常重要,但是你很难知道从哪里下手。对于一个性能不如预期的页面采用如下步骤:首先,对每一个函数的exclusive CPU时间进行排序,查看最消耗时间的函数列表。分析这些耗时的函数调用并进行重构和优化。

一旦做出了修改,让剖析工具再次检验新版本的程序,测试性能的改进。XHGui内置了完美的工具以比较两次运行;点击详细信息页面右上角的“Compare this run"按钮即可。该按钮会向你展示该URL每一次测试的结果,从中选择一个你要比较的对象。对你想比较的对象,点击”compare“按钮,XHGui将会转向比较视图,如下图所示:

使用XHGui来测试PHP性能的教程

 统计表格展示了新版和旧版统计信息的主要区别,包括每一个信息改动的实际数字以及百分比。上图显示,新版的请求等待时间仅仅为旧版的8%。统计表格详细展示了每一个统计信息的改变,这些统计信息我们在”详细信息“页面能够经常看到;你可以对任何一列进行排序以便查找你感兴趣的信息。

一旦你在某一方面成功的进行了重构,查看详细信息页面(detail page)以检查新版本的实际效果,然后挑选其他方面进行优化。尝试对内存使用或者exclusive wall time 进行排序,以便挑选能够最大限度提高应用整体性能的函数进行优化。同时,不要忘记检查调用的次数,一个重复调用的函数经过优化之后能够成倍的提高程序的性能。

最优化方法

你很难在量化成果之前知道自己改善了多少,这就是为什么我们经常在对一个应用进行优化之前检测它--不然你怎么知道自己是否真的优化了它?我们也需要想想一组真实的数据应该怎样表示,不然,我们可能会朝着一个不可能到达的目标前进。一个很有用的方法是:尽力去寻找需要使用的最适合的数据结构以及最小存储空间。如果在你擅长的工作环境中,不能在半秒内运行一个“Hello world”程序,那么就别指望用同样的工具构建的网页能有多好的表现。

上面的叙述并不是对编程框架(framework)的不敬;编程框架之所以存在是因为其方便使用、支持快速开发、容易维护。相比亲自手工编写代码,编程框架在性能上的降低是我们综合各方面进行折中的结果。采用编程框架进行应用开发是能够尽快上线的一种很好的方法,当需要的时候,你可以使用Profiling工具分析并改进程序的性能。例如,Zend Framework 1的很多模块能够提供非好强大的特性,但是并能非常低下;采用Profiling工具就能确定性能低下的部分并将它们进行替换。其他所有的框架都有类似的问题,XHGui能够向您展示问题的所在并检查他们是否对你的程序产生了可量化的影响。

在你的程序之外,一些其他的策略对占领上风或许迟早有用:

  •     当心非危险的慢速关联函数(not-dangerously-slow-but-related functions)在一个页面上露面。如果你的页面在格式化要点处理的 view helper 中的一系列函数中花去了它时间的 50%(我承诺这是个假想的例子),那么你可能想要去研究重构整个组件。
  •     少做。尝试移除特性,如果性能比它们重要。
  •     当心一个请求中生成但没有在特殊的视图中用到的内容,或未改变却被多次重新生成的内容。
  •     好的缓存策略。这将是关于它的另一篇文章,但是考虑用 PHP 中的一个 OpCode 缓存(从 PHP 5.5 起内置),在你的 web 服务器前方添加一个反向代理,简单地为那些不怎么经常改变的内容发送适当的缓存头。
  •     暴力去耦合。如果有一个可怕的资源紧张的特殊功能,把它从你的 web 服务器上去掉。或许它可以被异步处理,所以你的程序可以仅仅添加一个消息到队列,或移动到另一个单独的服务器并作为一个单独的服务模型来访问。无论哪种方式,分离将帮助减少你的 web 服务器的负载,同时启用了有效的扩展。

XHGui是你的朋友

XHGui安装简单、使用时如影随形、很棒的输出以至于可以拿到董事会议上进行展示。它能识别出我们应用中的错误,帮助我们确认应用真的起作用(或者没有!)。这可能会经历一些重复的过程,不过,不管你之前有没有用过XHProf、XHGui,我劝你花点时间在你的应用上试试,你会对你的发现大吃一惊。

PHP 相关文章推荐
PHP 常用函数库和一些实用小技巧
Jan 01 PHP
Ext.data.PagingMemoryProxy分页一次性读取数据的实现代码
Apr 07 PHP
利用PHP生成静态HTML文档的原理
Oct 29 PHP
php 获取SWF动画截图示例代码
Feb 10 PHP
php函数实现判断是否移动端访问
Mar 03 PHP
PHP常用的小程序代码段
Nov 14 PHP
优化WordPress中文章与评论的时间显示
Jan 12 PHP
Laravel使用Caching缓存数据减轻数据库查询压力的方法
Mar 15 PHP
yii2利用自带UploadedFile实现上传图片的示例
Feb 16 PHP
php数据库的增删改查 php与javascript之间的交互
Aug 31 PHP
Laravel框架运行出错提示RuntimeException No application encryption key has been specified.解决方法
Apr 02 PHP
laravel excel 上传文件保存到本地服务器功能
Nov 14 PHP
编写PHP脚本过滤用户上传的图片
Jul 03 #PHP
在Windows系统下使用PHP生成Word文档的教程
Jul 03 #PHP
深入理解PHP中的Streams工具
Jul 03 #PHP
列举PHP的Yii 2框架的开发优势
Jul 03 #PHP
PHP中异常处理的一些方法整理
Jul 03 #PHP
在PHP程序中使用Rust扩展的方法
Jul 03 #PHP
PHP整合七牛实现上传文件
Jul 03 #PHP
You might like
PHP在字符断点处截断文字的实现代码
2011/04/21 PHP
基于ubuntu下nginx+php+mysql安装配置的具体操作步骤
2013/04/28 PHP
超详细的php用户注册页面填写信息完整实例(附源码)
2015/11/17 PHP
PHP的Laravel框架中使用消息队列queue及异步队列的方法
2016/03/21 PHP
地址栏上的一段语句,改变页面的风格。(教程)
2008/04/02 Javascript
jquery学习笔记 用jquery实现无刷新登录
2011/08/08 Javascript
javascript获取url上某个参数的方法
2013/11/08 Javascript
深入理解JavaScript系列(25):设计模式之单例模式详解
2015/03/03 Javascript
Javascript aop(面向切面编程)之around(环绕)分析
2015/05/01 Javascript
JavaScript中的普通函数和箭头函数的区别和用法详解
2017/03/21 Javascript
从0到1搭建element后台框架优化篇(打包优化)
2019/05/12 Javascript
elementUI 动态生成几行几列的方法示例
2019/07/11 Javascript
js实现验证码干扰(静态)
2021/02/22 Javascript
简单文件操作python 修改文件指定行的方法
2013/05/15 Python
详解Python中的type()方法的使用
2015/05/21 Python
python Flask实现restful api service
2017/12/04 Python
python实现kNN算法
2017/12/20 Python
Python面向对象程序设计类变量与成员变量、类方法与成员方法用法分析
2019/04/12 Python
python实现批量修改服务器密码的方法
2019/08/13 Python
如何修复使用 Python ORM 工具 SQLAlchemy 时的常见陷阱
2019/11/19 Python
python运用pygame库实现双人弹球小游戏
2019/11/25 Python
python实现跨excel sheet复制代码实例
2020/03/03 Python
python爬虫开发之使用Python爬虫库requests多线程抓取猫眼电影TOP100实例
2020/03/10 Python
协程Python 中实现多任务耗资源最小的方式
2020/10/19 Python
AC Lens:购买隐形眼镜
2017/02/26 全球购物
几个Linux面试题笔试题
2016/08/01 面试题
财务人员个人自荐信范文
2013/09/26 职场文书
大一军训感言
2014/01/09 职场文书
学校机关党总支领导班子整改工作方案
2014/10/26 职场文书
销售内勤岗位职责
2015/02/10 职场文书
2015年办公室文员工作总结
2015/04/24 职场文书
超市员工管理制度
2015/08/06 职场文书
小学四年级作文之人物作文
2019/11/06 职场文书
Go语言实现Base64、Base58编码与解码
2021/07/26 Golang
使用javascript解析二维码的三种方式
2021/11/11 Javascript
字节飞书面试promise.all实现示例
2022/06/16 Javascript