Tag: 优化

  • 关于改善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的echo为什么这么慢

    作为一个行走江湖多年的老中医,今天受命去解决一例前端页面展现缓慢的问题。问题页的情况如下: apache + php 使用smarty模板输出内容 页面最终输出内容较大,80k+ 页面执行时间在500ms以上 祭出法宝xhprof对问题页面做了细致检查,发现页面的瓶颈竟然是模板(编译后的)中的一个echo语句,这个echo语句输出的字符串比较大,大概是50k+字节,花费时间为400多毫秒,占整个页面执行时间的80%。这样的echo输出在站点首页中其实是很常见的事情,没有数据库操作,按道理执行时间不应该这么长。 于是猛力使用搜索技能,最终在php手册的echo部分找到了一些蛛丝马迹,早在2003年就有前辈认为通过echo输出大字符串到客户端会引起服务器的性能问题,据我测试,在这个场景下使用print其实也是一样的慢。建议的解决办法是把字符串切割成更小的字符串输出,展现速度会有提升,输出函数如下: <?php function echobig($string, $bufferSize = 8192) { $splitString = str_split($string, $bufferSize); foreach($splitString as $chunk) echo $chunk; } ?> 但是上面的处方不太对症,整个echobig的输出时间仍然在400毫秒左右,没有太大改善。 考虑到是输出大量内容到客户端比较慢,于是检查了apache的配置,原来还没打开deflate进行压缩,遂启用之。再次使用xhprof进行检查,这条echo的输出时间降低到5ms左右。 400ms到5ms,一个配置问题会产生80倍的差距,还真是省老钱了。这个故事告诉我们,压缩输出真的很重要。 Update 实际上这个问题也可以通过调整webserver的output buffer来解决一部分,参考: Why echo is slow in PHP and how to make it really fast 加速PHP的ECHO

  • 在生产环境中使用php性能测试工具xhprof

    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真是酷毙了,哪段代码成为瓶颈,一目了然。

  • 用memcache.php监测memcache的状况

    最新的memcache pecl中,新增了一个memcache.php,这个php文件可以用来方便的查看memcache的状况,界面上与apc自带的apc.php风格一致。 如图: 应该算是最方便的监测memcache的办法了。 memcache.php源文件下载

  • 查看xdebug profile文件的几个程序

    在优化php代码执行效率过程中,有个好办法是利用xdebug生成profile文件,然后查看整个程序的瓶颈在哪里。现在xdebug profile的查看程序有好几个,在这里罗列一下. Wincachegrind Wincachegrind是windows下的profile查看程序,使用起来感觉还不错,profile文件太大的话偶尔会崩溃。 今天在高春辉的博客上看到这些: 最近又开始拿 Xdebug 和 wincachegrind 对项目的 PHP 代码进行分析和优化,但是发现和自己输出的执行时间总是相差十倍,差的不是零头,而是十倍。 上网搜索了一下,原来在 Xdebug 2.0.0RC4 版本开始,对 profiler 日志中的时间单位进行了修改。 (“Use µ seconds instead of a tenths of µ seconds to avoid confusion in profile information. ”) 而 wincachegrind 又不再升级维护了,所以凡是用 2.0.0RC4 以及之后版本的 Xdebug 输出的 profiler 日志用 wincachegrind 来分析的话,都会有十倍的时间差距。 他已经提供了hack后的版本,可以解决时间差距的问题,有兴趣的同学可以试试。 CachegrindVisualizer CachegrindVisualizer是一个xdebug的profile文件查看客户端,采用Adobe的AIR制作。 更详细的介绍可以看以前写的关于CachegrindVisualizer的介绍。 Kcachegrind Kcachegrind是linux下的一个图形化profile查看工具,功能很强劲。 Callgrind uses runtime […]

  • 如何避免使用php的require_once

    我们知道,在php中使用require_once/include_once虽然方便,但是代价昂贵,据测试数据来看,require_once比require慢3-4倍,所以在php开发中,我们应该尽量使用require/include。 列一下俺常用的避免require/include的方法。 使用__autoload php5可以使用__autoload来避免require,用的好的话,代码里头甚至看不到几个require,实在是安逸啊。测试结果表明,使用__autoload之后的new Foo; 比 require_once ‘foo.php’; new Foo; 大概要快3倍左右。 补充:为了避免autoload冲突,可以考虑使用spl_autoload_register(PHP 5 >= 5.1.2)来改变魔术函数__autoload的行为。 使用defined检测是否载入过 在代码开头使用defined检测是否定义过对应的常量,如果有的话,直接return。 <?php if(!defined(‘_MYCLASS_’)) return; define(‘_MYCLASS_’, 1); class MyClass { … } ?> 测试了一下,defined的性能也不是太好… require前检查 用class_exists或者function_exists检查一下,确认没有载入过再出手,至少比require_once能快上3倍。php4也可以用上。 class_exists(‘myClass’) or require(‘/path/to/myClass.class.php’);

  • 用xdebug优化php的三个小窍门

    xdebug的2.0正式版已经发布了。这个工具用在php的代码调试,优化方面效果很不错。下面贴上俺使用过程中的几个小窍门。 xdebug生成profile文件,可以用KCachegrind来查看,但是这个工具只在linux下面可用,没有windows下的版本。这里推荐一个win下的免费工具——wincachegrind,也可以查看xdebug的profile文件,用来分析php代码运行情况足够用了(偶尔不太稳定)。 xdebug一般情况下只会对一个请求做profile记录,如果需要查看几个请求的运行情况合集,可以设置xdebug.ini的 xdebug.profiler_aggregate = 1 记得重启你的apache。 如果在xdebug.ini里设置了 xdebug.profiler_enable = 1 那么每次程序运行期间xdebug都会记录profile,这样对程序的运行速度有很大的影响。为了避免这一情况发生,可以让xdebug仅在需要的时候运行——设置 xdebug.profiler_enable_trigger = 1 这样,只有你用get/post方式提交XDEBUG_PROFILE变量的情况下,xdebug才会开始干活。 另:将最新版本的xdebug和APC同时使用,没有出现兼容性问题,运行良好。

  • http_load的使用

    记得前些天介绍了一个幻灯——Getting Rich with PHP 5(IE之外的浏览器可看,见用php5来赚大钱),这个幻灯向我们展示了php程序优化的一些技巧,其中命令行工具http_load给我留下很深的印象,这工具看上去和apache的ab很相似,用来做网站的压力测试。昨天在服务器上安装http_load并试用了一段时间,下面是我的一点学习心得。 测试网站每秒所能承受的平均访问量 http_load -parallel 5 -fetches 1000 urls.txt 这段命令行是同时使用5个进程,随机访问urls.txt中的网址列表,总共访问1000次。运行之后的结果: 1000 fetches, 5 max parallel, 6e+06 bytes, in 58.1026 seconds 6000 mean bytes/connection 17.2109 fetches/sec, 103266 bytes/sec msecs/connect: 0.403263 mean, 68.603 max, 0.194 min msecs/first-response: 284.133 mean, 5410.13 max, 55.735 min HTTP response codes: code 200 — 1000 从上面的运行结果来看,目标网站仅仅能够承受每秒17次访问,不够强壮。 测试网站是否能承受住预期的访问压力 http_load -rate […]