php代码性能调优profile利器xhprof工作原理浅析

发表于:2013-01-30来源:Csdn作者:yzongyu点击数: 标签:xhprof
php代码性能调优profile利器xhprof工作原理浅析。 xhprof是php的第三方扩展,工作在zend层,以动态加载的方式被加载。php在解释执行的过程中,首先被解释成对应的token码,而后,编译成字节码(这里的字节码不是机器码,在PHP里面称其为opcode码)。xhprof就在php被加载

  xhprof的工作原理

  xhprof是php的第三方扩展,工作在zend层,以动态加载的方式被加载。php在解释执行的过程中,首先被解释成对应的token码,而后,编译成字节码(这里的字节码不是机器码,在PHP里面称其为opcode码)。xhprof就在php被加载,loading,引起自身extension的时候一起被加载,解释,编译。

  xhprof本身通过对zend层函数处理相关的结构体的定义,比如:

  zend_module_entry xhprof_module_entry = {

  #if ZEND_MODULE_API_NO >= 20010901

  STANDARD_MODULE_HEADER,

  #endif

  "xhprof", /* Name of the extension */

  xhprof_functions, /* List of functions exposed */

  PHP_MINIT(xhprof), /* Module init callback */

  PHP_MSHUTDOWN(xhprof), /* Module shutdown callback */

  PHP_RINIT(xhprof), /* Request init callback */

  PHP_RSHUTDOWN(xhprof), /* Request shutdown callback */

  PHP_MINFO(xhprof), /* Module info callback */

  #if ZEND_MODULE_API_NO >= 20010901

  XHPROF_VERSION,

  #endif

  STANDARD_MODULE_PROPERTIES

  };

  来完成xhprof自定义的函数的初始化,完成xhprof本身的callback机制的注册。

  在安装xhprof的过程中,我们需要去定义xhprof报告的输出目录,并且我们设置的时候,变量的名称只能是:xhprof.output_dir原因就在于在xhprof.c的文件中,对于php_ini_entry的设定就是

  PHP_INI_BEGIN()

  /* output directory:

  * Currently this is not used by the extension itself.

  * But some implementations of iXHProfRuns interface might

  * choose to save/restore XHProf profiler runs in the

  * directory specified by this ini setting.

  */

  PHP_INI_ENTRY("xhprof.output_dir", "", PHP_INI_ALL, NULL)

  PHP_INI_END()这里完成的对php.ini里有关xhprof的配置节的定义方式和方法。相关解释如下:

  如果想要为你的模块创建一个 .ini 文件的配置节,可以使用宏 PHP_INI_BEGIN() 来标识这个节的开始,并用 PHP_INI_END() 表示该配置节已经结束。然后在两者之间我们用 PHP_INI_ENTRY() 来创建具体的配置项。HP_INI_ENTRY() 总共接收 4 个参数:配置项名称、初始值、改变这些值所需的权限以及在值改变时用于接收通知的函数句柄。配置项名称和初始值必须是一个字符串,即使它们是一个整数。HP_INI_SYSTEM 只允许在 php.ini 中改变这些值;PHP_INI_USER 允许用户在运行时通过像 .htaccess 这样的附加文件来重写其值;而 PHP_INI_ALL 则允许随意更改。

  前面提到xhprof是在config.m4里面,作为$ext_shared的方式被动态加载进入zend层工作的,所以,这里还需要用zend_get_module进行一些处理。zend_get_module的作用为:

  ZEND_GET_MODULE (extension_name)

  Description:

  Provides additional C code used if you want to build a dynamic loaded extension.

  到这里,如果xhprof安装正常,那么就已经完成了php在启动的过程中,xhprof作为extension,被加载的方式的定义,和具体的方法的定义了。

  前面大体是xhprof在安装后,是工作在哪一层?以何种方式被引入php?怎么被引入的?相关理解和解释,下面再看看xhprof是怎么收集到函数的执行性能profile数据的,例如cpu、memory的使用等信息数据

  PHP_FUNCTION(xhprof_enable) {

  long xhprof_flags = 0; /* XHProf flags */

  zval *optional_array = NULL; /* optional array arg: for future use */

  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,

  "|lz", &xhprof_flags, &optional_array) == FAILURE) {

  return;

  }

  hp_get_ignored_functions_from_arg(optional_array);

  这个函数里面是对xhprof_enable函数体的实现,在我们需要对一个函数进行xhprof的时候,需要在最开始进行xhprof_enable()的调用,enable里面可以传参数也可以默认为空,这里zend_parse_parameters的参数中,"ZEND_NUM_ARGS() TSRMLS_CC"部分基本是固定打法,接着的部分 代表参数的相应类型。在这里"|lz"的意思是$xhprof_flags is long typeof,$optional_array is array typeof).

  zend_parse_parameters 详解

  自动生成的PHP函数周围包含了一些注释,这些注释用于自动生成代码文档和vi、Emacs等编辑器的代码折叠。函数自身的定义使用了宏PHP_FUNCTION(),该宏可以生成一个适合于Zend引擎的函数原型。逻辑本身分成语义各部分,取得调用函数的参数和逻辑本身。为了获得函数传递的参数,可以使用zend_parse_parameters()API函数

  所以如果获取xhprof_enable传入的参数如果失败,则会直接return。到下面,则是对hp_get_ignored_functions_from_arg的调用,看名字应该是对要忽略的函数名的获取,从该函数的本身内容

  static void hp_get_ignored_functions_from_arg(zval *args) {

  if (args != NULL) {

  zval *zresult = NULL;

  zresult = hp_zval_at_key("ignored_functions", args);

  hp_globals.ignored_function_names = hp_strings_in_zval(zresult);

  } else {

  hp_globals.ignored_function_names = NULL;

  }

  }可以看出,这个函数的确是对需要忽略的函数名的获取。

  这里插一脚,php之所以可以在使用变量前不需要对该变量进行提前定义,是因为在php的zend引擎中有这么一个东西zval,在php里面,zend用它来作为一个容器,来处理所有的外部变量,还是直接贴一段代码,大家一起来看

原文转自:http://blog.csdn.net/yzongyu/article/details/8457209