日誌未經聲明,均爲AlloVince原創。版權採用『 知識共享署名-非商業性使用 2.5 許可協議』進行許可。php
以前一直使用基於Xdebug進行PHP的性能分析,對於本地開發環境來講是夠用了,但若是是線上環境的話,xdebug消耗較大,配置也不夠靈活,所以線上環境建議使用xhprof進行PHP性能追蹤及分析。html
xhprof是Facebook開源的輕量級PHP性能分析工具,Linux環境下能夠經過pecl直接安裝,好比在Ubuntu下僅需3行指令mysql
pecl install xhprof-beta echo "extension=xhprof.so" > /etc/php5/fpm/conf.d/xhprof.ini service php5-fpm restart
以後能夠經過phpinfo()
檢查擴展是否已經加載。git
具體如何使用呢,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/
就能夠看到已經保存的結果,列出了全部函數的調用以及所消耗的時間。github
分析一下示例代碼sample.php
,關鍵部分只有2行:web
//開啓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
。sql
xhprof_html/index.php
將記錄的結果整理並可視化,默認的UI裏列出了:mongodb
每一項應該不難理解,以項目自帶的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安裝ubuntu
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數據以及展現數據的UI,聽起來彷佛又是一大堆工做,有現成的輪子能夠用嗎?
通過搜索和比較,貌似比較好的選擇有xhprof.io以及xhpgui。
兩個項目作得事情差很少,都提供了xhprof數據保存功能以及一套索引展現數據的UI,下面是一些比較
xhprof.io
xhgui
能夠看到其實兩個項目都不夠完善,相對而言xhgui不支持域名索引對於線上調試來講是沒法忍受的,所以我最後的選擇是使用xhprof.io,可是本身進行了微量的調整,修改後的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擴展是否安裝。
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();