xhprof php7问题

来源:互联网 发布:讨鬼传2最美捏脸数据 编辑:程序博客网 时间:2024/05/01 04:56

xhprof php7问题

xhprof 是facebook 开发的一个测试php性能的扩展,

现存的问题

xhprof不支持php7,代码已经几年没有更新过了, 由于Facebook的优化方向是HHVM,所以这个扩展可以预见不会再有官方维护了。

目前github上有一些个人维护的php7版本, 但是完成的质量都不高,存在各种坑,很不幸我们踩了一个: 内存泄漏

内存泄漏

test环境之前安装的版本:
https://github.com/RustJason/xhprof/tree/php7

之前用着一直好好的, 一经压测就完蛋了,原因就是内存泄漏。

用valgrind检测结果, 摘抄部分如下:

==19323== 32 bytes in 1 blocks are definitely lost in loss record 10 of 30==19323==    at 0x4C2210C: malloc (vg_replace_malloc.c:195)==19323==    by 0x7F76AA: __zend_malloc (zend_alloc.c:2853)==19323==    by 0xA5B9534: zend_string_alloc (zend_string.h:121)==19323==    by 0xA5B94DB: zend_string_init (zend_string.h:157)==19323==    by 0xA5B9E3F: hp_begin (xhprof.c:1688)==19323==    by 0xA5B7D4D: zif_xhprof_enable (xhprof.c:403)==19323==    by 0xA5B9B68: hp_execute_internal (xhprof.c:1586)==19323==    by 0x883CFC: ZEND_DO_FCALL_SPEC_HANDLER (zend_vm_execute.h:844)==19323==    by 0x882A30: execute_ex (zend_vm_execute.h:417)==19323==    by 0xA5B980C: hp_execute_ex (xhprof.c:1527)==19323==    by 0x882B47: zend_execute (zend_vm_execute.h:458)==19323==    by 0x82A134: zend_execute_scripts (zend.c:1427)...................等等...................==19323== LEAK SUMMARY:==19323==    definitely lost: 192 bytes in 6 blocks==19323==    indirectly lost: 0 bytes in 0 blocks==19323==      possibly lost: 0 bytes in 0 blocks==19323==    still reachable: 2,633 bytes in 26 blocks==19323==         suppressed: 0 bytes in 0 blocks==19323== Reachable blocks (those to which a pointer was found) are not shown.==19323== To see them, rerun with: --leak-check=full --show-reachable=yes

可以看到明显有内存泄漏: definitely lost: 192 bytes in 6 blocks
从上面的日志可以看出问题所在的调用栈:

xhprof_enable() -> hp_begin() -> zend_string_init() -> zend_string_alloc() -> __zend_malloc() -> malloc()

对着扩展的源码找一下问题出在哪:

static void hp_begin(long level, long xhprof_flags TSRMLS_DC) {    ................something.....................    BEGIN_PROFILING(&hp_globals.entries, zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 1), hp_profile_flag);    return;    ..............................

这块申请了内存, 但是并没有进行释放!看了下代码这个问题有些复杂, 下面这个结构体是一个全局变量保存了所有php函数的调用栈, 以及每个函数用的时间、cpu使用等信息。zend_string 是用来保存函数名的,就是这一块的内存发生了泄漏。由于这是一个全局变量, 整体代码中这个结构体耦合非常高, 改起来不容易。

typedef struct hp_entry_t {  zend_string             *name_hprof;                       /* function name */  int                     rlvl_hprof;        /* recursion level for function */  uint64                  tsc_start;         /* start value for TSC counter  */  long int                mu_start_hprof;                    /* memory usage */  long int                pmu_start_hprof;              /* peak memory usage */  struct rusage           ru_start_hprof;             /* user/sys time start */  struct hp_entry_t      *prev_hprof;    /* ptr to prev entry being profiled */  uint8                   hash_code;     /* hash_code for the function name  */

而且,这个版本完成的质量不高,其作者也在readme中提到”
Please do not use this in an production env.生产环境勿用。代码简直没法看。

所以我放弃直接修复这个版本的bug, 而选择寻找其他方案

解决办法

在尝试解决问题的时候发现了一个扩展Tideways, 这是基于xhprof的二次开发版本,是一整套解决方案(包括xhprof,以及性能分析的图形化界面等等)。需要注意的是这是一个这是一个商业版本, 其中图形化性能分析工具是收费的, xhprof功能是免费的, 对我们来说已经够用了。

测试了一下:

  1. 用法与xhprof一样,功能没有问题,满足我们需求
  2. valgrind检测无内存泄漏
  3. 压测内存未见异常。
0 0
原创粉丝点击