当前位置:首页 > PHP教程 > php高级应用 > 列表

PHP性能分析工具XHProf深入分析

发布:smiling 来源: PHP粉丝网  添加日期:2018-10-31 22:51:02 浏览: 评论:0 

多次调用xhprof_enable方法,最后生效的配置是哪个?

当你在一次请求中多次调用xhprof_enable方法,只有第一次调用时进行的设置能生效。在调用.

xhprof_disable()后,你又可以使用xhprof_enable方法进行设置。

  1. $i = 0; 
  2. function good(){ 
  3.     global $i
  4.     $i++; 
  5.     if ($i < 2) { 
  6.         good(); 
  7.     } 
  8. function func() { 
  9.     good(); 
  10. $start_time = microtime(true); 
  11. xhprof_enable(XHPROF_FLAGS_NO_BUILTINS); 
  12. xhprof_enable(XHPROF_FLAGS_MEMORY + XHPROF_FLAGS_CPU + XHPROF_FLAGS_NO_BUILTINS); 
  13. for ($i = 0; $i < 100; $i++) { 
  14.     func(); 
  15. good(); 
  16. $rst = xhprof_disable(); 
  17. var_dump($rst); 

输出内容为:

  1. array(5) { 
  2.   ["good==>good@1"]=> 
  3.   array(2) { 
  4.     ["ct"]=> 
  5.     int(1) 
  6.     ["wt"]=> 
  7.     int(70) 
  8.   } 
  9.   ["func==>good"]=> 
  10.   array(2) { 
  11.     ["ct"]=> 
  12.     int(50) 
  13.     ["wt"]=> 
  14.     int(121) 
  15.   } 
  16.   ["main()==>func"]=> 
  17.   array(2) { 
  18.     ["ct"]=> 
  19.     int(50) 
  20.     ["wt"]=> 
  21.     int(135) 
  22.   } 
  23.   ["main()==>good"]=> 
  24.   array(2) { 
  25.     ["ct"]=> 
  26.     int(1) 
  27.     ["wt"]=> 
  28.     int(0) 
  29.   } 
  30.   ["main()"]=> 
  31.   array(2) { 
  32.     ["ct"]=> 
  33.     int(1) 
  34.     ["wt"]=> 
  35.     int(237) 
  36.   } 

可见,打印的内容,并没有cpu和memory的信息。

输出内容中的ct,wt,cpu,mu, pmu 都代表什么意思.

ct 表示 调用的次数

wt 表示 函数方法执行的时间耗时。相当于,在调用前记录一个时间,函数方法调用完毕后,计算时间差。

cpu 表示 函数方法执行消耗的cpu时间。和wt的差别在于,当进程让出cpu使用权后,将不再计算cpu时间。通过调用系统调用getrusage获取进程的占用cpu数据。

mu 表示 函数方法所使用的内存。相当于,在调用前记录一个内存占用,函数方法调用完毕后,计算内存差。调用的是zend_memory_usage获取内存占用情况。

pmu 表示 函数方法所使用的内存峰值。调用的是zend_memory_peak_usage获取内存情况。

输出内容中good==>good@1 是什么意思

==>表示一个调用关系。由于带@,说明是一个递归调用。@后面的数字是递归调用的深度。

如何设置xhprof_enable的参数,减少性能消耗

xhprof_enable提供了三个常量,用于设置你是否需要统计PHP内置函数,都统计那些指标。

三个常量如下:

XHPROF_FLAGS_NO_BUILTINS

设置这个常量后,将不统计PHP内置函数。毕竟PHP的内置函数性能一般都不错。没必要再消耗性能去统计。所以,建议设置。

XHPROF_FLAGS_CPU

设置这个常量后,会统计进程占用CPU时间。由于CPU时间是通过调用系统调用getrusage获取,导致性能比较差。开启这个选项后,大概性能下降一半。因此,如果对cpu耗时不是特别敏感的情况下,建议不要启用这个选项。

XHPROF_FLAGS_MEMORY

设置这个常量后,将会统计内存占用情况。由于获取内存情况,使用的是zend_memory_usage和zend_memory_peak_usage,并不是系统调用。因此,对性能影响不大。如果需要对内存使用情况进行分析的情况下,可以开启。

性能分析原理

如何实现对各个函数方法性能数据记录

目前xhprof会对,加载PHP文件,执行PHP函数方法,和执行eval方法进行性能数据记录。正好,这些在PHP内核中,有对应的函数进行处理。当你调用xhprof_enable方法时,会把默认的方法替换为xhprof的方法。来看看相关代码吧。

  1. static void hp_begin(long level, long xhprof_flags) 
  2.     if (!hp_globals.enabled) 
  3.     { 
  4.         int hp_profile_flag = 1; 
  5.  
  6.         hp_globals.enabled = 1; 
  7.         hp_globals.xhprof_flags = (uint32) xhprof_flags; 
  8.  
  9.          /* Replace zend_compile with our proxy */ 
  10.                  /* 处理加载PHP文件 */ 
  11.                  /* 先把zend引擎默认处理方法保存到_zend_compile_file变量中。*/ 
  12.         _zend_compile_file = zend_compile_file; 
  13.                 /* 在把xhprof相对应的方法赋值给zend_compile_file。 
  14.                    这样,每次加载PHP文件时,就会执行xhprof相应的方法。*/ 
  15.         zend_compile_file  = hp_compile_file; 
  16.  
  17.         /* Replace zend_compile_string with our proxy */ 
  18.                 /* 处理eval代码的执行 */ 
  19.         _zend_compile_string = zend_compile_string; 
  20.         zend_compile_string  = hp_compile_string; 
  21.  
  22.         /*init the execute pointer*/ 
  23.                 /* 处理 函数方法的执行 */ 
  24.         _zend_execute_ex = zend_execute_ex; 
  25.         zend_execute_ex  = hp_execute_ex; 
  26.               ......... 
  27.     } 
  28.  
  29. /*那我们看下,hp_compile_file方法,又是如何实现的*/ 
  30. ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type) 
  31.     const char *filename; 
  32.     char *func; 
  33.     int len; 
  34.     zend_op_array *ret; 
  35.     int hp_profile_flag = 1; 
  36.  
  37.     filename = hp_get_base_filename(file_handle->filename); 
  38.     len = sizeof("load") - 1 + strlen(filename) + 3; 
  39.     func = (char *) emalloc(len); 
  40.     snprintf(func, len, "load::%s", filename); 
  41.  
  42.         //方法执行前记录当前各项性能如数,如cpu 内存等 
  43.     BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag); 
  44.         //开始zend引擎相应的方法,加载文件 
  45.     ret = _zend_compile_file(file_handle, type); 
  46.     if (hp_globals.entries) 
  47.     { 
  48.                 //加载文件完毕后,再次记录当前各项性能数据。以便以后计算差值。 
  49.         END_PROFILING(&hp_globals.entries, hp_profile_flag); 
  50.     } //phpfensi.com 
  51.  
  52.     efree(func); 
  53.     return ret; 

xhprof在实现的时候,性能方面做了哪些优化

获取时间时,为了性能,使用了汇编来获取时间戳计数器。时间秒 = 时间戳计数器值 / CPU主频。

正是这种实现,导致目前xhprof还只适用于x86架构。此外,因为RDTSC的数据不能在CPU间同步,所以,xhprof会将进程绑定在单个CPU上。

如果SpeedStep技术是打开的,XHProf的基于RDTSC定时器的功能就不能正常工作了。这项技术在某些英特尔处理器上是可用的。[注:苹果台式机和笔记本电脑一般都将SpeedStep技术预设开启。使用XHProf,您需要禁用SpeedStep技术。 ]

  1. inline uint64 cycle_timer() 
  2.     uint32 __a, __d; 
  3.     uint64 val; 
  4.     asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); 
  5.     (val) = ((uint64) __a) | (((uint64) __d) << 32); 
  6.     return val; 

Tags: PHP性能分析 XHProf

分享到: