読者です 読者をやめる 読者になる 読者になる

PHPプロファイラ XHProf と XHGui と Callgraph をインストール

こんにちは、エンジニアのあらきです。
最近、外はめっきり寒くなってきました。

うちのマンションは昭和生まれということで気密性が低いです。さらに窓や扉の高さが低いため、午前中でも奥まで光が入ってきません。
なので朝と夜はメチャ寒い。特に朝。
もうね、ほんと、布団が恋しい(´ー`)
身体が重くて布団から出られません(´ー`)

・・・

重いといえば!

色々と開発をしている中で、いつの間にかやたらと表示が重いページが出てきます。何秒とかかかります。メモリが256MBだとか、回線がISDNだとかではありません。

「いったいどこが重いねん(゚д゚)」

ってことで、Facebook製のPHPプロファイラ『XHProf』をローカル環境にインストールして、どのメソッドがノロマな亀になっているのかを探りました。

環境

  • PHP 5.6
  • nginx(今回はSSLページに設定)
  • MySQL

目標

XHProfで取得した情報を、XHGuiとCallgraphで確認できるようにして、ボトルネックを発見する

XHProfのインストール

まずはXHProfのインストールをしましょう。

$ pecl install channel://pecl.php.net/xhprof-0.9.4

次にphp.iniを編集してインストールしたXHProfを認識させます。

$ vim /etc/php.ini

# 最終行でいいので、以下を入力
[xhprof]
extension=xhprof.so

ウェブサーバーを再起動して、インストールの確認をします。

# nginxを再起動
$ /etc/init.d/nginx restart

# インストール確認
$ php --ri xhprof

xhprof => 0.9.2

XHGuiのインストール

続いてXHGuiのインストールです。

XHGuiのダウンロード

まずはXHGuiをダウンロードしましょう。
(今回は直接ファイルをダウンロードする形で進めていきます)
https://github.com/pierrejoye/xhprof-pr
f:id:i-plug-develop:20161101164421j:plain

ダウンロードしたzipを解凍。xhprof-prフォルダをドキュメントルートに設置します。

# xhprof-pr → xhprofにリネームしました
$ ~/public_html/xhprof

$ cd ~/public_html/xhprof

各種ファイルの編集

次に各種ファイルの編集を行っていきます。

# header.phpファイル
$ vim external/header.php
// コメントアウト
register_shutdown_function('xhprof_shutdown_function');
 ↓
// register_shutdown_function('xhprof_shutdown_function');

configファイルはサンプルからコピーを作成します

# サンプルからコピーを作成
cp xhprof_lib/config.sample.php xhprof_lib/config.php
// DBの情報を適宜設定
$_xhprof['dbtype'] = 'mysql'; // Only relevant for PDO
$_xhprof['dbuser'] = 'user';
$_xhprof['dbpass'] = 'password';
$_xhprof['dbname'] = 'xhprof';
$_xhprof['dbadapter'] = 'Pdo';
$_xhprof['url'] = 'https://xhprof.example.jp';
// $controlIPs = falseを有効に
// $controlIPs = false;
$controlIPs = array();
$controlIPs[] = "127.0.0.1";
$controlIPs[] = "::1";
 ↓
$controlIPs = false;
// $controlIPs = array();
// $controlIPs[] = "127.0.0.1";
// $controlIPs[] = "::1";`|

データベースの設定

次にデータベースの設定を行います。

-- MySQLにDB名『xhprof』を作成
mysql> CREATE DATABASE xhprof;

続いてテーブルを作成しますが、xhprof_lib/utils/Db/Pdo.phpの冒頭にCreate table文がコメントアウトで記載されているので、それをそのまま実行します。

$ vim xhprof_lib/utils/Db/Pdo.php
mysql> CREATE TABLE `details` (
         `id` char(17) NOT NULL,
         `url` varchar(255) default NULL,
         ...

nginxの設定

次にnginxの設定を行っていきましょう。 まずは、おおもとのnginx.confにconf.d以下のconfファイルを読み込む設定をします。

http {
    ...

    include /etc/nginx/conf.d/*.conf;
}

続いて、xhprof用のconfファイルを作成します。

$ vim /etc/nginx/conf.d/xhprof-ssl.conf
server {
    listen       443;
    server_name  xhprof.example.jp;

    ssl on;
    ssl_certificate /etc/nginx/ssl.hoge.crt;
    ssl_certificate_key /etc/nginx/ssl.hoge.key;

    set_real_ip_from   172.31.0.0/16;
    real_ip_header     X-Forwarded-For;

    root   /home/example/xhprof/xhprof_html/;
    index  index.html index.php;

    location = /robots.txt { access_log off; log_not_found off; }
    location = /favicon.ico { access_log off; log_not_found off; }

    location ~ \.(php|phar)$ {
        expires off;
        include /etc/nginx/fastcgi_params;
        fastcgi_pass 127.0.0.1:9000;
        fastcgi_index index.php;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    }

    location ~ /\. {
        deny all;
        access_log off;
        log_not_found off;
    }
}

そして、解析するサイトのconfファイルにxhprofのheader.phpとfooter.phpを読み込むように設定

$ vim /etc/nginx/conf.d/example-ssl.conf
location ~ \.(php|phar)$ {
    include /etc/nginx/fastcgi_params;

    ...

    # 以下を追加
    fastcgi_param PHP_VALUE "auto_prepend_file=/var/www/example/public/xhprof/external/header.php \n auto_append_file=/var/www/example/public/xhprof/external/footer.php";
}

ここまで設定できたらnginxとphp-fpmを再起動します。

$ /etc/init.d/nginx restart
$ /etc/init.d/php-fpm restart

設定は以上です。

XHProfでの解析のON/OFFと解析データ確認

解析

XHProfでの解析を行う場合、解析したいページURLに『_profile=1』パラメータをつけてアクセスします。
https://example.jp?_profile=1
アクセスすると、以降停止するまで自動で解析し続けます。
ページ遷移をした場合は、遷移先のページが解析されます。

解析を停止するには、URLに『_profile=0』をつけてアクセスします。
https://example.jp?_profile=0

データ確認

/etc/hostに以下を追記して

# IPは適宜変更してください
192.168.33.10  xhprof.example.jp

ページにアクセスすれば、解析されたデータが確認できます。
https://xhprof.example.jp
f:id:i-plug-develop:20161101164352j:plain

Callgraphのインストール

最後にコールグラフをインストールします。

$ yum install graphviz graphviz-gd

xhprofのconfig.phpの以下のコメントアウトを外す

$ vim xhprof_lib/config.php
/*
$_xhprof['dot_binary']  = '/usr/bin/dot';
$_xhprof['dot_tempdir'] = '/tmp';
$_xhprof['dot_errfile'] = '/tmp/xh_dot.err';
*/

 ↓

$_xhprof['dot_binary']  = '/usr/bin/dot';
$_xhprof['dot_tempdir'] = '/tmp';
$_xhprof['dot_errfile'] = '/tmp/xh_dot.err';

コールグラフ確認

https://xhprof.example.jpにアクセスして、該当データのTimestampをクリック
→ View Callgraphをクリック → 以下のようなコールグラフが表示されればOKです
f:id:i-plug-develop:20161101164247j:plain

まとめ

というわけで、無事ノロマな亀を発見することができました(えらい重たいクエリが...)

こういうボトルネックとなる部分が、視覚的にパッとわかるのは(・∀・)イイネ!!
私みたいな未熟者には大変助かります。神Facebook