PHPのパフォーマンス測定用ツールxhprofをubuntu+nginxの環境で使うやり方をまとめています。やりたい事自体はubuntu以外のOSやapache等でも応用できるはずです。
インストール方法は本家含めて色々なとこで記述されているかと思うのですが、実際に恒常的に使うとなるまでに関しての資料があまり見つからず、またそのまま使うには少々不便な所がある(タグを入れたり等)ので、今回まとめました。
検証した環境
ubuntu 14.04.5
nginx 1.10.1
PHP 5.5.9
xhprofのインストール
サーバ上で必要ファイルのインストール。rootもしくはsudoで実行。
apt-get install graphviz
apt-get install libgv-php5
pecl install xhprof-0.9.4
xhprofを有効にする。xhprof.output_dirにはxhprofのプロファイルデータ保存先。
データを残しておきたい場合は/tmp以外を指定してください。
echo "extension=xhprof.so" > /etc/php5/mods-available/xhprof.ini
echo "xhprof.output_dir=/tmp" >> /etc/php5/mods-available/xhprof.ini
php5enmod xhprof
確認、0.9.2がインストールされているが特に利用に支障はないので気にせず進める
php -i|grep xhprof
/etc/php5/cli/conf.d/20-xhprof.ini
xhprof
xhprof => 0.9.2
プロファイル画面の設置
cd /var/www
git clone https://github.com/phacility/xhprof.git
nginxの設定
http://<ドメイン or IP>/xhprof/で見れるように設定。
/var/www/html/xhprofに必要ファイル一式をおいても良いのだが、今回はhtml以下を汚さない方針で以下の様に設置
server {
listen 80;
server_name <<your domain>>;
root /var/www/html;
(略)
#PHP実行設定
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
#xhprof/以下でxhpforを見るための設定
location ^~ /xhprof {
alias /var/www/xhprof/xhprof_html;
index index.php index.html index.htm;
location ~ \.php$ {
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_split_path_info ^(/xhprof)(/.*)$;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $request_filename;
fastcgi_buffers 16 16k;
fastcgi_buffer_size 32k;
include fastcgi_params;
}
}
}
nginx,php5-fpmをリロード
nginx -s reload
service php5-fpm restart
xhprof/以下で画面表示した際に画面ではパスがルート直下になっており、css,js等がでないのとリンクが全て死ぬ。
設定する所が見つからなかったので、以下の様に対応。(やり方として恐らく間違っているので、正しいやり方があればご指摘ください。。。)
45行目付近
/**
* Our coding convention disallows relative paths in hrefs.
* Get the base URL path from the SCRIPT_NAME.
*/
// $base_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
// ↓
$base_path = "/xhprof".rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
59行目付近
if (empty($ui_dir_url_path)) {
//$ui_dir_url_path = rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
// ↓
$ui_dir_url_path ='/xhprof'. rtrim(dirname($_SERVER['SCRIPT_NAME']), '/\\');
}
プロファイル実行用スクリプト設置
スクリプト作成
基本的にやることはxhprofのプロファイル開始と終了だが、
プロファイルするしないを自由に制御できる様にパラメーターとcookieで実行を制御する。
<?php
$isExecuteXhprof=false;
if(isset($_COOKIE['is_execute_xhprof']) && $_COOKIE['is_execute_xhprof']==1){
$isExecuteXhprof=true;
}
if(isset($_REQUEST['xhprof'])){
if($_REQUEST['xhprof']=='1'){
$isExecuteXhprof=true;
setcookie('is_execute_xhprof',1);
} elseif($_REQUEST['xhprof']=='0'){
$isExecuteXhprof=false;
setcookie('is_execute_xhprof',0);
}
}
if($isExecuteXhprof){
xhprof_enable();
}
<?php
if($isExecuteXhprof){
//プロファイル終了
$xhprof_data = xhprof_disable();
//データ保存
$XHPROF_ROOT = "/var/www/xhprof/";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_lib.php";
include_once $XHPROF_ROOT . "/xhprof_lib/utils/xhprof_runs.php";
$xhprof_runs = new XHProfRuns_Default();
$run_id = $xhprof_runs->save_run($xhprof_data, "xhprof_foo");
//表示、ログ出力、etc
echo '<br /><a id="xhprof_result_link" href="http://'.$_SERVER['HTTP_HOST'].'/xhprof/index.php?run='.$run_id.'&source=xhprof_foo" target="_blank">xhprof</a>';
}
スクリプト設置
以下どちらかの方で開始と終了の設定を読み込む。
nginxの設定で読み込む
nginxに以下の様にfastcgi_paramにPHP_VALUEを設定すれば、ページ実行時に強制的に入れてくれる。
#PHP実行設定
location ~ \.php$ {
(略)
fastcgi_param SCRIPT_FILENAME $document_root/$fastcgi_script_name;
#以下を追加
fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/xhprof/xhprof_profile_start.php \n auto_append_file=/var/www/xhprof/xhprof_profile_finish.php";
(略)
}
nginx -s reload
プログラム上でincludeする
//プロファイル開始のところに入れる
include('/var/www/xhprof/xhprof_profile_start.php');
(計測したい処理)
//プロファイル終了のところに入れる
include('/var/www/xhprof/xhprof_profile_finish.php');
動作確認
正常に設定されて入れば、パラメータにxhprof=1をつけて、ページの最下部にリンクが表示されるはずです。
一度パラメータをつけるとプロファイルし続け、xhprof=0とするとプロファイルをしなくなります。
遷移先でもプロファイル結果が正しく表示され、リンク等も問題なく遷移できれば正常にインストールされています。ページによっては表示の設定等で最下部が見れない場合もあるので、以下の様なブックマークレットを使うと便利です。
プロファイルページを出す用のブックマークレット
javascript:(function(){var%20d=window.document;if(d.getElementById("xhprof_result_link")){window.open(d.getElementById("xhprof_result_link").href);}else{alert("xhprofのリンクが取得できませんでした。xhprofが実行されていないか、処理が中断されていないか等確認ください。");}
})();void(0);