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

來源:互聯網
上載者:User


常見問題

多次調用xhprof_enable方法,最後生效的配置是哪個?
當你在一次請求中多次調用xhprof_enable方法,只有第一次調用時進行的設定能生效。在調用
xhprof_disable()後,你又可以使用xhprof_enable方法進行設定。

$i = 0;
function good(){
    global $i;
    $i++;
    if ($i < 2) {
        good();
    }
}
function func() {
    good();
}
$start_time = microtime(true);
xhprof_enable(XHPROF_FLAGS_NO_BUILTINS);
xhprof_enable(XHPROF_FLAGS_MEMORY + XHPROF_FLAGS_CPU + XHPROF_FLAGS_NO_BUILTINS);
for ($i = 0; $i < 100; $i++) {
    func();
}
good();
$rst = xhprof_disable();
var_dump($rst);

輸出內容為:

array(5) {
  ["good==>good@1"]=>
  array(2) {
    ["ct"]=>
    int(1)
    ["wt"]=>
    int(70)
  }
  ["func==>good"]=>
  array(2) {
    ["ct"]=>
    int(50)
    ["wt"]=>
    int(121)
  }
  ["main()==>func"]=>
  array(2) {
    ["ct"]=>
    int(50)
    ["wt"]=>
    int(135)
  }
  ["main()==>good"]=>
  array(2) {
    ["ct"]=>
    int(1)
    ["wt"]=>
    int(0)
  }
  ["main()"]=>
  array(2) {
    ["ct"]=>
    int(1)
    ["wt"]=>
    int(237)
  }
}

可見,列印的內容,並沒有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的方法。來看看相關代碼吧。

static void hp_begin(long level, long xhprof_flags)
{
    if (!hp_globals.enabled)
    {
        int hp_profile_flag = 1;

        hp_globals.enabled = 1;
        hp_globals.xhprof_flags = (uint32) xhprof_flags;

         /* Replace zend_compile with our proxy */
                 /* 處理載入PHP檔案 */
                 /* 先把zend引擎預設處理方法儲存到_zend_compile_file變數中。*/
        _zend_compile_file = zend_compile_file;
                /* 在把xhprof相對應的方法賦值給zend_compile_file。
                   這樣,每次載入PHP檔案時,就會執行xhprof相應的方法。*/
        zend_compile_file  = hp_compile_file;

        /* Replace zend_compile_string with our proxy */
                /* 處理eval代碼的執行 */
        _zend_compile_string = zend_compile_string;
        zend_compile_string  = hp_compile_string;

        /*init the execute pointer*/
                /* 處理 函數方法的執行 */
        _zend_execute_ex = zend_execute_ex;
        zend_execute_ex  = hp_execute_ex;
              .........
    }
}

/*那我們看下,hp_compile_file方法,又是如何?的*/
ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type)
{
    const char *filename;
    char *func;
    int len;
    zend_op_array *ret;
    int hp_profile_flag = 1;

    filename = hp_get_base_filename(file_handle->filename);
    len = sizeof("load") - 1 + strlen(filename) + 3;
    func = (char *) emalloc(len);
    snprintf(func, len, "load::%s", filename);

        //方法執行前記錄當前各項效能如數,如cpu 記憶體等
    BEGIN_PROFILING(&hp_globals.entries, func, hp_profile_flag);
        //開始zend引擎相應的方法,負載檔案
    ret = _zend_compile_file(file_handle, type);
    if (hp_globals.entries)
    {
                //負載檔案完畢後,再次記錄當前各項效能資料。以便以後計算差值。
        END_PROFILING(&hp_globals.entries, hp_profile_flag);
    }

    efree(func);
    return ret;
}

xhprof在實現的時候,效能方面做了哪些最佳化

擷取時間時,為了效能,使用了彙編來擷取時間戳記計數器。時間秒 = 時間戳記計數器值 / CPU主頻。
正是這種實現,導致目前xhprof還只適用於x86架構。此外,因為RDTSC的資料不能在CPU間同步,所以,xhprof會將進程綁定在單個CPU上。
如果SpeedStep技術是開啟的,XHProf的基於RDTSC定時器的功能就不能正常工作了。這項技術在某些英特爾處理器上是可用的。[註:蘋果台式機和膝上型電腦一般都將SpeedStep技術預設開啟。使用XHProf,您需要禁用SpeedStep技術。 ]

inline uint64 cycle_timer()
{
    uint32 __a, __d;
    uint64 val;
    asm volatile("rdtsc" : "=a" (__a), "=d" (__d));
    (val) = ((uint64) __a) | (((uint64) __d) << 32);
    return val;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.