基于在生产环境中使用php性能测试工具xhprof的详解


Posted in PHP onJune 03, 2013

xhprof 是facebook开源出来的一个php性能测试工具,也可以称之为profile工具,这个词不知道怎么翻译才比较达意。跟之前一直使用的xdebug相比,有很多类似之处。以前对xdebug有一些记录还可以供参考,但是它的缺点是对性能影响太大,即便是开启了profiler_enable_trigger参数,用在生产环境中也是惨不忍睹,cpu立刻就飙到high。
而xhprof就显得很轻量,是否记录profile可以由程序控制,因此,用在生产环境中也就成为一种可能。在它的文档上可以看到这样一种用法:
以万分之一的几率启用xhprof,平时悄悄的不打枪。

if (mt_rand(1, 10000) == 1) {
 xhprof_enable(XHPROF_FLAGS_MEMORY);
 $xhprof_on = true;
}

在程序结尾处调用方法保存profile
if ($xhprof_on) {
 // stop profiler
 $xhprof_data = xhprof_disable(); // save $xhprof_data somewhere (say a central DB)
 ...
}

也可以用register_shutdown_function方法指定在程序结束时保存xhprof信息,这样就免去了结尾处判断,给个改写的不完整例子:
if (mt_rand(1, 10000) == 1) {
 xhprof_enable(XHPROF_FLAGS_MEMORY);
 register_shutdown_function(create_funcion('', "$xhprof_data = xhprof_disable(); save $xhprof_data;"));
}

至于日志,我暂时用的是最土的文件形式保存,定期清除即可。
BTW:xhprof生成的图形方式profile真是酷毙了,哪段代码成为瓶颈,一目了然。
by phpe:下面是一个例图:

基于在生产环境中使用php性能测试工具xhprof的详解

关于改善xhprof使用情况的设想
自从去年将xhprof用在生产环境以来,对生产环境的程序调试,性能优化都带来很多便利。但是在使用过程中,还是有一些细节需要改善。
问题
xhprof的profile日志直接以文件形式保存在生产服务器上,需要定时清理,或者收集起来移动到查看日志的工具机上。
由于xhprof生成的profile是一个大数组,所以保存到文件时使用了标准的php serialize,日志文件偏大,一个不留神就容易占用很多服务器磁盘空间。
查看日志列表时,一个个点开查看比较费劲。
针对这几个问题,我有一些小小的设想。
日志存放
部署一个中央日志服务器,采用facebook的scribe来收集日志。生产环境的服务器产生的xhprof日志,都写入到scribe的客户端,由客户端自动同步到中央日志服务器的scribe上,不占用本地的存储空间。在代码上的改动也比较小,只要基于iXHProfRuns接口实现一个XhprofRuns类,调整save_run方法的存储方式即可。
更换序列化方法
xhprof默认是将profile信息用php原生的序列化方法处理后进行保存,而我在前两天比较过igbinary vs serialize vs json_encode的性能和占用字节数,这个测试里igbinary在各方面都有一定优势,尤其是占用存储空间会大幅度减小,所以我只要更换序列化方法为igbinary_serialize即可获得改善。
优化列表展示
我已经厌倦挨个查看profile日志的大图,费时费力还没有针对性。所以我现在的做法是,在profile日志的列表中将前1000个日志的总体执行时间直接输出到列表中,并且将执行时间过长的日志用红色粗体标识。做了这个小小的改动之后,当我想要去视察一下运行情况时,就把日志列表中那些红通通的链接点开看看就行了,真正的省时省力。
如何从xhprof日志文件中获取执行时间?简单的代码如下

/**
* 由xhprof日志获得执行时间
*
* @param string $log xhprof日志的文件路径
* @return int 执行时间
*/
function getSpentTime($log) {
  $profile = unserialize(file_get_contents($log));
  return $profile['main()']['wt'] / 1000;
}

PHP 相关文章推荐
php部分常见问题总结
Mar 27 PHP
php 数组的一个悲剧?
May 11 PHP
PHP的异常处理类Exception的使用及说明
Jun 13 PHP
解析php 版获取重定向后的地址(代码)
Jun 26 PHP
PHP修改session_id示例代码
Jan 08 PHP
ThinkPHP单字母函数(快捷方法)使用总结
Jul 23 PHP
非常实用的PHP常用函数汇总
Dec 17 PHP
php返回字符串中所有单词的方法
Mar 09 PHP
php定义参数数量可变的函数用法实例
Mar 16 PHP
php性能分析之php-fpm慢执行日志slow log用法浅析
Oct 17 PHP
ecshop适应在PHP7的修改方法解决报错的实现
Nov 01 PHP
PhpStorm 如何优雅的调试Hyperf的方法步骤
Nov 24 PHP
php cli模式学习(PHP命令行模式)
Jun 03 #PHP
获取PHP警告错误信息的解决方法
Jun 03 #PHP
php cli 小技巧
Jun 03 #PHP
php中用加号与用array_merge合并数组的区别深入分析
Jun 03 #PHP
PHP在线生成二维码代码(google api)
Jun 03 #PHP
深入探讨:Nginx 502 Bad Gateway错误的解决方法
Jun 03 #PHP
深入php-fpm的两种进程管理模式详解
Jun 03 #PHP
You might like
PHP无敌近乎加密方式!
2010/07/17 PHP
php xml常用函数的集合(比较详细)
2013/06/06 PHP
微信第三方登录(原生)demo【必看篇】
2017/05/26 PHP
Laravel中unique和exists验证规则的优化详解
2018/01/28 PHP
详解php协程知识点
2018/09/21 PHP
如何在PHP中使用AES加密算法加密数据
2020/06/24 PHP
aspx中利用js实现确认删除代码
2010/07/22 Javascript
js中有关IE版本检测
2012/01/04 Javascript
jQuery简单图表peity.js使用示例
2014/05/02 Javascript
通过$(this)使用jQuery包装后的方法或属性
2014/05/18 Javascript
jQuery实现个性翻牌效果导航菜单的方法
2015/03/09 Javascript
jQuery实现的登录浮动框效果代码
2015/09/26 Javascript
微信小程序 九宫格实例代码
2017/01/21 Javascript
如何使用bootstrap框架 bootstrap入门必看!
2017/04/13 Javascript
vue 动态绑定背景图片的方法
2018/08/10 Javascript
Vue中使用方法、计算属性或观察者的方法实例详解
2018/10/31 Javascript
vue子路由跳转实现tab选项卡
2019/07/24 Javascript
微信小程序返回上一页传参并刷新过程解析
2019/12/13 Javascript
浅谈Vue static 静态资源路径 和 style问题
2020/11/07 Javascript
javascript实现倒计时提示框
2021/03/02 Javascript
Python遍历指定文件及文件夹的方法
2015/05/09 Python
python实现百万答题自动百度搜索答案
2018/01/16 Python
深入理解Django-Signals信号量
2019/02/19 Python
Python分布式进程中你会遇到的问题解析
2019/05/28 Python
python利用re,bs4,requests模块获取股票数据
2019/07/29 Python
python中pdb模块实例用法
2021/01/15 Python
CSS3中线性颜色渐变的一些实现方法
2015/07/14 HTML / CSS
施华洛世奇水晶荷兰官方网站:SWAROVSKI荷兰
2017/05/12 全球购物
Java面向对象面试题
2016/12/26 面试题
化工专业大学生职业生涯规划书
2014/01/14 职场文书
商务日语专业自荐信
2014/04/17 职场文书
2014年国庆标语
2014/06/30 职场文书
给朋友的道歉短信
2015/05/12 职场文书
2019各种承诺书范文
2019/06/24 职场文书
解决Goland 同一个package中函数互相调用的问题
2021/05/06 Golang
Netty结合Protobuf进行编解码的方法
2021/06/26 Java/Android