Home > Uncategorized > Debugging PHP with xhprof

Debugging PHP with xhprof

大概一个星期之前些的,后来稍有修改,一直躺在我硬盘,再后来一忙就忘了发了。其实我也不想在这个喜庆的日子里发这种东西…

一般性的php调试技术,参考下有新浪认证的 @Laruence 大神提到的 PHP调试技术手册

调试自己不熟悉的代码比较费力。如果代码是自己写的,发现问题后,看错误提示,看程序写的日志文件,看php_error.log,基本都能找到问题。discuz 代码结构挺复杂,功能繁杂到变态,我也懒得学,一般有问题直接调。

我一般用 xhprof 调试dz(之前有过案例,参考 http://liruqi.cn/?p=20001)。本来 xhprof 项目本意做php 的 profiler, 大概就是根据统计函数执行时间(准确而言是函数a调用函数b的次数以及总时间),找出项目的性能瓶颈。但是面对一套自己不熟悉的代码,要找个问题,我也只能用 xhprof(呃,其它工具比如 xdebug 我也没用过)。调试的关键在于,你要找到程序出错的位置。发现有人在stackoverflow 上问了一个很蛋疼的问题:怎么最快地判断PHP脚本退出的位置(http://stackoverflow.com/questions/216963/fastest-way-to-determine-where-php-script-exits)。因为最近论坛从dz7.2 升级到x1.5,之前给外部产品用的用户注册、登录api失效了。重新改的时候,出现因为缺少宏定义造成 access deny,然后直接退出… 然后我也很想知道程序究竟在哪个地方 access deny… 然后用关键词 “register_shutdown_function debug_backtrace” google到了这个问题:想法很简单,希望在退出之前看一看函数调用栈。但是看了帖子讨论就知道,一步到位方法目前并不存在,因为register_shutdown_function 所定义的回调函数,在被调用时,函数栈已经清空了,而且也没有替代的方式可以在清站之前做些回调之类的。

看看下面这段代码:

 46 if (function_exists(“xhprof_enable”)) {
 47     xhprof_enable(0,
 48             array(‘ignored_functions’ =>  array(‘call_user_func’,
 49                     ‘call_user_func_array’)));
 50     function xhprof_write_tmp_file($name=””) {
 51         $xhprof_data = xhprof_disable();
 52 #uasort($xhprof_data, create_function(‘$a,$b’, ‘return $a[“wt”]<$b[“wt”];’));
 53         file_put_contents(“/tmp/x15.goapk.com.$name”, var_export($xhprof_data, true));
 54     }
 55     register_shutdown_function(“xhprof_write_tmp_file”, “exit”);
 56 }
  … (需要做profile的代码段)
 2012 xhprof_write_tmp_file(“end”);

跟上篇文章贴的代码段不同之处在于,这里注册了脚本退出时的回调函数。如果程序是正常执行完,会在/tmp 目录下生成 .end 文件;如果中间退出,则是 .exit。用这套代码,最开始的目的是查找一个在论坛的注册时,CGI超时的问题。因为是超时,脚本不能正常退出,xhprof_disable 写在代码尾部也打不出log,所以想到用这种方式。这种方式的确很高效,很容易追踪的超时的函数 (后来找到原因是 dz 给新注册用户发送通知邮件时超时导致的)。如果是出错调试,也可以用这种方式跟踪代码,看走到什么地方,没有按照预期继续往下走,然后在出问题的位置输出调试信息。相对而言,这种方式比自己瞎猜要快得多。回到上面“怎么最快地判断PHP脚本退出的位置”的问题,我认为这种方式是一个不错的方案;而另外一些时候,程序出错也会走不同的程序分支,可以在xhprof 数据中体现出来。总而言之,我们可以根据 xhprof生成的函数调用信息,判断出代码执行过程(如果有类似shell 里面的 sh -x 执行方式就更好了- -,但是如果有循环,这种方式也会产生大量输出,同样需要花些时间分析日志),从而定位问题。所以,我认为 xhprof 是个挺高效的php 调试工具。

上次为了修复注册、登录 api 搭上了几乎一整天时间。最后连蒙带猜搞定了,泪流满面… 我实在是不想看uccenter 的bullshit api… 如果这玩意当初就是用uccenter 的 api 写的,倒也不用改代码了,上uccenter 改个设置就行。

Advertisements
Categories: Uncategorized
  1. No comments yet.
  1. No trackbacks yet.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: