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功能是免費的, 對我們來說已經夠用了。
測試了一下:
用法與xhprof一樣,功能沒有問題,滿足我們需求valgrind檢測無內存泄漏壓測內存未見異常。新聞熱點
疑難解答
圖片精選