介紹
XHProf 是一個分層 PHP 效能分析工具。它報告函式級別的請求次數和各種指標,包括阻塞時間,CPU時間和記憶體使用情況。一個函式的開銷,可細分成呼叫者和被呼叫者的開銷,XHProf 資料收集階段,它記錄呼叫次數的追蹤和包容性的指標弧在動態 callgraph 的一個程式。它獨有的資料計算的報告/後處理階段。在資料收集時,XHProfd通過檢測迴圈來處理遞迴的函式呼叫,並通過給遞迴呼叫中每個深度的呼叫一個有用的命名來避開死迴圈。XHProf分析報告有助於理解被執行的程式碼的結構,它有一個簡單的 HTML的 使用者介面( PHP寫成的)。基於瀏覽器的效能分析使用者介面能更容易檢視,或是與同行們分享成果。也能繪製呼叫關係圖。
簡單說就是檢視 PHP 效能和耗時情況
Docker安裝
本文演示使用倉庫 dnmp
- 啟動 PHP 容器並進入容器
docker exec -it php71 sh
- 使用 docker-php-extension 安裝 Xhprof 擴充套件
install-php-extensions xhprof
php -m
檢視 xhprof 擴充套件
使用
安裝成功後,可以在 PHP 程式碼中使用,使用 tp,在 public/index.php 檔案中新增程式碼
//開始分析
\xhprof_enable();
require __DIR__ . '/../vendor/autoload.php';
// 要進行分析的程式碼,執行HTTP應用並響應
$http = (new App())->http;
//分析結束,並獲取分析結果
$xhprof_data = \xhprof_disable();
var_dump($xhprof_data);
exit;
$xhprof_data 變數儲存程式執行過程中所有的函式呼叫時間及 CPU 記憶體消耗
具體記錄哪些指標可以通過 xhprof_enable 的引數控制,目前支援的引數有:
- HPROF_FLAGS_NO_BUILTINS 跳過所有內建(內部)函式。
- XHPROF_FLAGS_CPU 輸出的效能資料中新增 CPU 資料。
- XHPROF_FLAGS_MEMORY 輸出的效能資料中新增記憶體資料。
訪問 tp 框架,列印分析結果
可以看到,雖然成功分析出來結果,但是資料對我們不是太友好
對分析結果,可以通過 xhprof 自帶的 lib 庫生成到一個檔案裡面,然後通過 xhprof 自帶的 html 來顯示
xhprof_html 來顯示分析結果
配置 xhprof_html 的訪問域名,以便我們進行訪問
在 php 容器的根目錄下 通過 find -name xhprof_html
搜尋擴充套件生成的 html 的位置
在 /usr/local/lib/php
資料夾下,可看到兩個資料夾 xhprof_html
,xhprof_lib
xhprof_html: 進行分析結果網頁顯示的html
xhprof_lib: 對分析結果進行其它處理的類庫
配置訪問域名
複製 xhprof_html,xhprof_lib 檔案到 nginx
的 對外訪問目錄,我的 PHP 容器的 www 對映的就是 nginx 的訪問目錄,不在一個容器,可以先複製到宿主機,然後在複製到 nginx 容器內
# 建立 nginx 的目錄
/www # mkdir /www/xhprof
/www # mkdir /www/xhprof/xhprof_html
/www # mkdir /www/xhprof/xhprof_lib
#複製 xhprof_html,xhprof_lib 到新建立的目錄
/www/xhprof # cp -R /usr/local/lib/php/xhprof_html/* /www/xhprof/xhprof_html/
/www/xhprof # cp -R /usr/local/lib/php/xhprof_lib/* /www/xhprof/xhprof_lib
nginx 配置域名,並重啟 nginx 服務
server {
listen 80;
server_name xhprof.li;
root /www/xhprof/xhprof_html;
index index.php index.html index.htm;
#charset koi8-r;
access_log /dev/null;
#access_log /var/log/nginx/nginx.localhost.access.log main;
error_log /var/log/nginx/nginx.xhprof-li.error.log warn;
location = /50x.html {
root /usr/share/nginx/html;
}
location / {
if (!-e $request_filename) {
rewrite ^(.*)$ /index.php?s=$1 last;
break;
}
}
location ~ \.php$ {
fastcgi_pass php71:9000;
fastcgi_split_path_info ^((?U).+\.php)(/?.+)$;
include fastcgi-php.conf;
include fastcgi_params;
}
}
分析結果顯示檔案
配置生成的檔案輸出目錄,
PHP.ini
,手動建立下,注意許可權
[xhprof] # 注意目錄是否有許可權生成檔案 xhprof.output_dir = /www/xhprof
重啟 PHP 服務
docker-compose restart php71
更改程式碼,ThinkPHP6 index.php
<?php // [ 應用入口檔案 ] namespace think; //xhprof-開始分析 \xhprof_enable(); require __DIR__ . '/../vendor/autoload.php'; //xhprof-要進行分析的程式碼,執行HTTP應用並響應 //----------------------------------------- $http = (new App())->http; //----------------------------------------- //xhprof-分析結束,並獲取分析結果 $xhprof_data = \xhprof_disable(); //xhprof-引入類庫,進行分析結果的儲存 include_once "/www/xhprof/xhprof_lib/utils/xhprof_lib.php"; include_once "/www/xhprof/xhprof_lib/utils/xhprof_runs.php"; // save raw data for this profiler run using default // implementation of iXHProfRuns. $xhprof_runs = new \XHProfRuns_Default(); // xhprof - 儲存資料到 xhprof-test 檔案 $run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_test"); dd($run_id); $response = $http->run(); $response->send(); $http->end($response);
執行 tp 框架,生成檔案
開啟剛剛配置 xhprof 域名
顯示結果
欄位名 | 含義 |
---|---|
Calls | 呼叫次數 |
Incl. Wall Time | 呼叫的包括子函式所有花費時間,以微秒算 |
Excl. Wall Time | 函式執行本身花費的時間,不包括子樹執行時間,以微秒算 |
Incl. CPU | 呼叫的包括子函式所有花費的cpu時間 |
Excl. CPU | 函式執行本身花費的cpu時間,不包括子樹執行時間,以微秒算 |
Incl.MemUse | 包括子函式執行使用的記憶體, 以位元組算 |
Excl.MemUse | 函式執行本身記憶體,以位元組算 |
Incl.PeakMemUse | Incl.MemUse的峰值 |
可以點選 [View Full Callgraph] 連結,檢視視覺化分析圖
如果報錯 failed to execute cmd: " dot -Tsvg". stderr: 'sh: dot: not found '
, 大概率是缺少依賴 graphviz
安裝 graphviz
graphviz 是一個繪製圖形的工具,可以更為直觀的讓你檢視效能的瓶頸。
docker 容器內使用 apk
進行安裝
- 進入 PHP71 容器
docker exec -it php71 sh
- 安裝 graphviz
apk add graphviz --repository=http://dl-cdn.alpinelinux.org/alpine/edge/main
- 再次點選 [View Full Callgraph]
接入專案
在上面演示中,是直接通過修改框架的入口檔案 index.php 來進行分析的,但不可能每個專案我們都需要修改原始碼
其實 PHP 本身就提供了更好的注入方式,將上述邏輯儲存到 xhprof_inject.php 檔案中,然後修改 PHP 配置檔案中的 auto_prepend_file 配置,這樣所有的 PHP 請求檔案都會自動注入 xhprof_inject.php 這個檔案,這樣侵入性更小,並且可以實現基於站點的注入。
/www/xhprof/xhprof_inject.php
<?php //開啟xhprof xhprof_enable(XHPROF_FLAGS_MEMORY | XHPROF_FLAGS_CPU); //在程式結束後收集資料 register_shutdown_function(function() { $xhprof_data = xhprof_disable(); //讓資料收集程式在後臺執行 if (function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); } //xhprof-引入類庫,進行分析結果的儲存 include_once "/www/xhprof/xhprof_lib/utils/xhprof_lib.php"; include_once "/www/xhprof/xhprof_lib/utils/xhprof_runs.php"; // save raw data for this profiler run using default // implementation of iXHProfRuns. $xhprof_runs = new \XHProfRuns_Default(); // xhprof - 儲存資料到 xhprof-test 檔案 $xhprof_runs->save_run($xhprof_data, "xhprof_test"); });
- 更改
PHP.ini
或新增nginx引數
更改完重啟 PHP 容器; Automatically add files before PHP document. ; http://php.net/auto-prepend-file auto_prepend_file =/www/xhprof/xhprof_inject.php
如果不想修改 PHP 配置檔案,也可修改 Nginx 的 fastcgi_param
修改完後重啟 Nginx 服務fastcgi_param PHP_VALUE "auto_prepend_file=/www/xhprof/xhprof_inject.php";
本作品採用《CC 協議》,轉載必須註明作者和本文連結