PHPパフォーマンスチューニング

夏休み記事2件目です。

PHPのパフォーマンスチューニングする場合、どの部分がボトルネックになっているか把握しないといけません。
今回は、Xdebugとwebgrindを使ったプロファイリングをやってみたのでまとめます。
なお、本記事の画像は、プログラムの情報が漏れないようぼかしています。

# とりあえずどのように見えるのか紹介
Xdebugでphpのプロファイリングをしてそのアウトプットをwebgrindで表示すると以下のような感じになります。
![スクリーンショット 2020-08-10 13.31.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/a0afa85a-109a-5357-b47d-12a7932c5b37.png)

- 実行された関数名
- 呼び出し回数
- その関数自身の全体に対する処理時間の割合（％）、または実行時間（msec / usec)
- 実行するのにかかった総時間

が表示されます。
処理の流れをわかりやすくグラフで表示することもできます。
![スクリーンショット 2020-08-10 13.35.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/de08515a-3b86-97aa-1ff4-e7c61efb44d5.png)

それでは、使用するための準備をしていきます。
なお、本記事の実行環境は、以下の通りです。

- プロファイリングしたい対象サーバ（docker）
    - centOS
    - Apache

# Xdebug
## インストール
プロファイリングしたい物が入っているサーバーで、以下のように実行していきます。

```bash:bash
# ここは使いたいPHPのバージョンにあったものを選択してください（https://xdebug.org/download/historical）
curl -OL https://xdebug.org/files/xdebug-2.2.0RC1.tgz 
tar -xzf xdebug-2.2.0RC1.tgz
cd xdebug-2.2.0RC1
phpize
./configure --enable-xdebug
make
make install
```

最後の`make install`したときの出力にモジュールの場所が出てきるので、これをメモってください。
（例）`/usr/lib64/php/modules/xdebug.so`
これで、Xdebugのインストールは終了です。

## 設定と有効化
それではこれを使用するために、`php.ini`をいじっていきます。
もし、`php.ini`の場所がわからない場合は、以下のものを実行するとわかります。

```bash:bash
php --ini
```

場所がわかったところで、php.iniを編集していきます。

```ini:php.ini
; ファイルの末尾に以下を追加します。
zend_extension="(さっきメモったパス)/xdebug.so"
; プロファイリングを有効化
xdebug.profiler_enable = 1
; プロファイルの結果を吐き出す場所の指定(デフォルトは/tmpなのでなくても良い)
xdebug.profiler_output_dir=/tmp
```

## プロファイリング
ここまでやったら、webサーバーを再起動しましょう

```bash:bash
# apacheの例
service httpd restart
```

これで、プロファイリングしたいページを見ると、先ほど結果を吐き出す場所に指定したところにプロファイリング結果が出ていると思います。
続いて、この結果を見やすくするためにwebgrindを準備していきたいと思います。

# webgrindの準備
[ここ](https://github.com/jokkedk/webgrind)にインストール手順が載っています。
今回は、プロファイリング対象とは別で使いたいので、dockerを使用してみます。

```bash:bash
docker run --rm -v /(ここにプロファイル結果が保存されているパスを指定):/tmp -p 80:80 jokkedk/webgrind:latest
```

## 見やすく表示してみる
これでwebgrindは使えます。
プロファイリング対象と同じサーバーで動かしたい場合は[ここ](https://github.com/jokkedk/webgrind#installation)を見てやってみてください。

それでは、[http://localhost:80/index.php](http://localhost:80/index.php)にアクセスすると、以下のような画面が出てくると思います。

![スクリーンショット 2020-08-10 15.52.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/b2f86328-e930-29b3-c3fc-2aa123372046.png)

右上の機能の説明は左から、

- show:(処理時間がかかった順に)どれほど表示するか（100%にすると、全ての処理が表示されます。）
- Auto(newest):表示させるプロファイリング結果、デフォルトは、一番新しいファイル
- percent:表示単位を(percent / milliseconds / microseconds)から選択

これで`update`を押すと、設定が反映されます。
そうすると以下のように表示されると思います。
![スクリーンショット 2020-08-10 13.31.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/46ac6d1e-db93-f928-ce89-addbfdf81399.png)
上でも書いたように、

- 実行された関数名
- 呼び出し回数
- その関数自身の全体に対する処理時間の割合（％）、または実行時間（msec / usec)
- 実行するのにかかった総時間

が表示されます。
この時、関数名の左に色のついた丸があると思います。
調べた結果、丸の色の意味は以下のようです。

|色|説明|
|---|---|
|青|PHPの標準関数|
|緑|自分で定義したクラスメソッド|
|オレンジ|手続き型の関数|
|グレー|include、またはrequire .phpファイルにかかる時間|

処理の流れをわかりやすくグラフで表示することもできます。
100%でやった場合下の画像のように自分の環境ではとても膨大になりました。
![スクリーンショット 2020-08-10 13.30.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323051/b8563852-5f9b-ef8c-f3e6-247ca6ff8cf1.png)

これで、どこの処理で時間をかかっているのか把握しやすくなりました。
これを使いつつ、該当の関数の修正などを行っていけば、いい感じにチューニングできそうですね！

# 参考にさせていただいた記事など
- [パフォーマンスも大事！〜PHPでプロファイリング編〜](http://tech.innovation.co.jp/2018/07/30/P-H-P.html)
- [WordPress サイトのボトルネックを見つける為の解析ツール紹介|セルティスラボ](https://celtislab.net/archives/20140418/wordpress-profiler/)
- [jokkedk/webgrind](https://github.com/jokkedk/webgrind)
- [xdebug.org](https://xdebug.org/)