使用xhprof進行線上PHP效能追蹤及分析
之前一直使用基於Xdebug進行PHP的效能分析,對於本地開發環境來說是夠用了,但如果是線上環境的話,xdebug消耗較大,配置也不夠靈活,因此線上環境建議使用xhprof進行PHP效能追蹤及分析。
xhprof的安裝與簡易用法
xhprof是Facebook開源的輕量級PHP效能分析工具,Linux環境下可以通過pecl直接安裝,比如在Ubuntu下僅需3行指令
pecl install xhprof-beta
echo "extension=xhprof.so" > /etc/php5/fpm/conf.d/xhprof.ini
service php5-fpm restart
之後可以通過phpinfo()
檢查擴充套件是否已經載入。
具體如何使用呢,xhprof專案中已經提供了示例以及簡易的UI,下載xhprof專案到web伺服器,假設可以通過http://localhost/xhprof/
訪問,那麼訪問http://localhost/xhprof/examples/sample.php
可以看到一些輸出,並且提示通過訪問http://<xhprof-ui-address>/index.php?run=XXX&source=xhprof_foo
檢視結果。接下來訪問http://localhost/xhprof/xhprof_html/
就可以看到已經儲存的結果,列出了所有函式的呼叫以及所消耗的時間。
分析一下示例程式碼sample.php
,關鍵部分只有2行:
//開啟xhprof並開始記錄
xhprof_enable();
//執行一些函式
foo();
//停止記錄並取到結果
$xhprof_data = xhprof_disable();
$xhprof_data
中記錄了程式單步執行過程中所有的函式呼叫時間及CPU記憶體消耗等,具體記錄哪些指標可以通過xhprof_enable
的入口引數控制,之後的處理已經與xhprof擴充套件無關,大致是編寫了一個儲存類XHProfRuns_Default
,將$xhprof_data
序列化並儲存到某個目錄,可以通過XHProfRuns_Default(__DIR__)
將結果輸出到當前目錄,如果不指定則會讀取php.ini配置檔案中的xhprof.output_dir
,仍然沒有指定則會輸出到/tmp
。
xhprof_html/index.php
將記錄的結果整理並視覺化,預設的UI裡列出了:
- funciton name : 函式名
- calls: 呼叫次數
- Incl. Wall Time (microsec): 函式執行時間(包括子函式)
- IWall%:函式執行時間(包括子函式)佔比
- Excl. Wall Time(microsec):函式執行時間(不包括子函式)
- EWall%:函式執行時間(不包括子函式)
每一項應該不難理解,以專案自帶的sample.php
為例,示例中編寫了一個main()
函式,main()
函式中呼叫foo()
、bar()
等一些子函式進行了一點字元處理。整個程式執行過程中,main()
函式只執行了一次,並且由於main()
函式中包括了所有的邏輯,所以main()
函式的IWall%佔比為100%,但是由於main()
函式的功能都是由子函式實現的,因此main()
函式的EWall%只有0.3%,而foo()
函式完成了主要的工作,EWall%有98.1%。因此在分析更大型的程式時,往往需要根據這幾項指標分別排序,從不同的角度審視效能消耗。
在xhprof_html/index.php
中還可以看到[View Full Callgraph]
連結,點選後可以繪製出一張視覺化的效能分析圖,如果點選後報錯的話,可能是缺少依賴graphviz
,ubuntu可以通過apt安裝
apt-get install graphviz
更好的注入方式
瞭解了上面這些,其實就已經可以將xhprof整合到任何我們已有的專案中去了。目前大部分MVC框架都有唯一的入口檔案,只需要在入口檔案的開始處注入xhprof的邏輯
//開啟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資料
...
});
但是這樣免不了要修改專案的原始碼,其實php本身就提供了更好的注入方式,比如將上述邏輯儲存為/opt/inject.php
,然後修改php fpm配置檔案
vi /etc/php5/fpm/php.ini
修改auto_prepend_file
配置
auto_prepend_file = /opt/inject.php
這樣所有的php-fpm請求的php檔案前都會自動注入/opt/inject.php
檔案
如果使用Nginx的話,還可以通過Nginx的配置檔案設定,這樣侵入性更小,並且可以實現基於站點的注入。
fastcgi_param PHP_VALUE "auto_prepend_file=/opt/inject.php";
更好的分析工具:xhprof.io還是xhpgui
注入程式碼後我們還需要實現儲存xhprof資料以及展示資料的UI,聽起來似乎又是一大堆工作,有現成的輪子可以用嗎?
經過搜尋和比較,貌似比較好的選擇有xhprof.io以及xhpgui。
兩個專案做得事情差不多,都提供了xhprof資料儲存功能以及一套索引展示資料的UI,下面是一些比較
xhprof.io
- ✗ 年久失修
- ✗ 儲存xhprof資料到MySQL
- ✓ 支援域名、URI等多個維度的資料索引
- ✓ 函式呼叫記錄完整,核心級別函式都能顯示
- ✗ 無法針對個別URI開啟
- ✗ 注入被分割成兩個檔案,如果程式被強制中斷時xhprof資料將無法收集
xhgui
- ✓ 儲存xhprof資料到MongoDB
- ✗ 不支援域名索引
- ✗ 函式呼叫記錄不完整,部分核心級別函式(如擴充套件內)無法顯示
- ✓ 有配置檔案可以控制開啟條件
- ✓ 注入只有一個檔案
- ✓ 狂拽酷炫的基於D3.js的呼叫關係動態圖
可以看到其實兩個專案都不夠完善,相對而言xhgui不支援域名索引對於線上除錯來說是無法忍受的,因此我最後的選擇是使用xhprof.io,但是自己進行了微量的調整,修改後的xhprof.io修正版支援:
- ✓ 增加開啟開關配置,可以針對個別URI開啟
- ✓ 注入檔案合併為一個
xhprof.io修正版安裝與使用
安裝及配置方法如下,假設web伺服器根目錄為/opt/htdocs
cd /opt/htdocs
git clone https://github.com/EvaEngine/xhprof.io.git
cd xhprof.io/
composer install
cp xhprof/includes/config.inc.sample.php xhprof/includes/config.inc.php
vi xhprof/includes/config.inc.php
在MySQL中建立xhprof.io資料庫,假設資料庫名為xhprof
,然後匯入xhprof/setup/database.sql
配置檔案config.inc.php
中需要調整
'url_base' => 'http://localhost/xhprof.io/',
這是xhprof.io介面所在路徑'pdo' => new PDO('mysql:dbname=xhprof;host=localhost;charset=utf8', 'root', 'password'),
根據MySQL實際情況調整配置enable
這是一個匿名函式,當匿名函式返回true時啟用xhprof資料收集
通過配置enable
項,就可以實現線上除錯的需求,比如
始終開啟xhprof
'enable' => function() {
return true;
}
1/100概率隨機開啟xhprof
'enable' => function() {
return rand(0, 100) === 1;
}
網頁攜帶引數debug=1時開啟xhprof
'enable' => function() {
return !empty($_GET['debug']);
}
網頁URL為特定路徑時開啟
'enable' => function() {
return strpos($_SERVER['REQUEST_URI'], '/testurl') === 0;
}
最後按上文所述,在要配置的專案中包含xhprof.io/inc/inject.php
即可。
線上環境操作時務必要膽大心細,如果沒有結果尤其注意需要檢查xhprof擴充套件是否安裝。
附錄:xhpgui的安裝方法
apt-get install mongodb php5-mongo php5-mcrypt
cp /etc/php5/mods-available/mcrypt.ini /etc/php5/fpm/conf.d/
cp /etc/php5/mods-available/mcrypt.ini /etc/php5/cli/conf.d/
cd /opt/htdocs
git clone https://github.com/perftools/xhgui.git
cd xhgui
composer install
cp config/config.default.php config/config.php
chown www-data.www-data -R cache
編輯Nginx配置檔案加入
fastcgi_param PHP_VALUE "auto_prepend_file=/opt/htdocs/xhgui/external/header.php";
收集資料過多時可以清空mongodb
mongo
use xhprof;
db.dropDatabase();
相關文章
- PHP 效能追蹤及分析工具(XHPROF)PHP
- php效能分析利器:xhprofPHP
- Docker中使用Xhprof 對程式碼進行效能分析Docker
- Laradock 下使用 Tideways_xhprof+Xhgui 進行效能分析 —— 安裝篇IDEGUI
- Centos下給PHP7新增Xhprof效能分析CentOSPHP
- 使用 XDebug + Webgrind 進行 PHP 程式效能分析WebPHP
- 使用 tideways_xhprof + xhgui 分析 PHP 執行情況IDEGUIPHP
- 使用pprof進行效能分析
- 使用應用程式跟蹤對效能改變進行量化分析(轉)
- ORACLE 使用TRACE進行SQL效能分析OracleSQL
- 使用ErrorStack進行錯誤跟蹤及診斷Error
- 使用ErrorStack進行錯誤跟蹤及診斷!Error
- 使用VisualVM對JAVA程式進行效能分析及調優LVMJava
- SQL追蹤和事件追蹤SQL事件
- 使用ErrorStack進行Oracle錯誤跟蹤及診斷ErrorOracle
- 使用ERRORSTACK進行錯誤跟蹤及診斷(轉)Error
- 使用 CSS 追蹤使用者CSS
- 線上環境 Linux 系統呼叫追蹤Linux
- 利用神器BTrace 追蹤線上 Spring Boot應用執行時資訊Spring Boot
- golang 程式記憶體追蹤、分析Golang記憶體
- 使用 Unity 開發 Android 遊戲時如何追蹤效能問題UnityAndroid遊戲
- Oracle執行語句跟蹤 使用sql trace實現語句追蹤OracleSQL
- 使用DBMS_PROFILER進行PL/SQL效能分析SQL
- MYSQL sql執行過程的一些跟蹤分析(二.mysql優化器追蹤分析)MySql優化
- PHP7 安裝 xhprofPHP
- 使用dbms_system 追蹤sqlSQL
- 利用perf進行效能分析
- 使用火焰圖進行Java應用效能分析Java
- 使用 Spark 進行微服務的實時效能分析Spark微服務
- 線上追蹤壓縮後的JS出錯程式碼JS
- 如何透過鏈路追蹤進行定時任務診斷
- iOS安全攻防(十六):使用introspy追蹤分析應用程式iOSROS
- 使用 SonarQube 追蹤程式碼問題
- 追蹤專案進展常用的衡量方法
- 匿名網路追蹤溯源機制及方法
- 如何使用專案問題追蹤軟體跟進管理專案
- 日誌追蹤
- 程式碼追蹤