[LaravelなどのFWにも使える]PHP処理のパフォーマンスを計測するツール【Blackfire】が最高だった


先日、会社のプロジェクトの開発で検索APIなるものをLaravelで作っていました。
作っていて思ったこと「なんか速度遅くね?」
検索APIの速度はCVRにも直結し、離脱を防ぐためになんとしても速度を早くしてくれというリーダーからの要望。

まず大事なのが「処理のどこが遅くボトルネックになってるのか」を洗い出す必要があった。Laravelは速度的には早くないで有名だが、そこは一旦置いておいてプロジェクトで書かれたビジネスロジックの部分に何か問題があるものとして、遅い原因の特定をすることにしました。

ただ、計測といっても闇雲に探すのは時間の浪費。
一つ一つの処理を一々確認していったら日が暮れてしまう。。。
そこでPHPのパフォーマンスツール「Blackfire」というものがあったので試してみた。

こんな感じで計測結果がグラフとフローチャートっぽく見ることができます。
一つの処理にどれだけ時間がかかっているのか可視化出来るので結構便利。

PHPのパフォーマンス計測ツール「BlackFire」とは

計測ツール。現状はPHPしか完全対応していませんが、BetaとしてPythonやGoも対応しています。とりあえず以下必要なもの。

  • Blackfireの会員登録
  • Blackfireのアカウントに紐付いたIDやTOKEN
  • Chromeの拡張機能

使用するには会員登録が必要です(個人利用は無料。
あとは、計測結果を確認するためにChromeの拡張機能が必要です。(コンソールから計測を行うのであれば入れる必要はないけど、計測結果のグラフなどが見やすいので入れることをお勧めします。

ドキュメントが基本的に英語なのがちょっと面倒。後、日本だとあんまり使われていないのかドキュメントが基本的に少ないので分からない部分は頑張って模索するしかない。

会員登録を済ませて、SERVER_ID SEVER_TOKENClient_ID Client_TOKENを発行する。この二つがないと使えないので。
登録後以下のページからコピペできます。
https://blackfire.io/my/settings/credentials

PHPをプロファイルングするツール【BlackFire】のインストール方法

大体、使いたい人は既存で構築している環境に組み込みたいと思う人がほとんどだと思うので、それを仮定して行います(僕もそうだった)
やり方は人それぞれなのと、意外と設定方法は多いので試してみてください。
公式》https://blackfire.io/docs/introduction

DockerですでにPHPコンテナを立ち上げられる状態と仮定します。
Dockerfileの中に以下の記述追記。

FROM php:7.3-fpm-alpine
*** 省略 ****
RUN version=$(php -r "echo PHP_MAJOR_VERSION.PHP_MINOR_VERSION;") \
    && curl -A "Docker" -o /tmp/blackfire-probe.tar.gz -D - -L -s https://blackfire.io/api/v1/releases/probe/php/alpine/amd64/$version \
    && mkdir -p /tmp/blackfire \
    && tar zxpf /tmp/blackfire-probe.tar.gz -C /tmp/blackfire \
    && mv /tmp/blackfire/blackfire-*.so $(php -r "echo ini_get ('extension_dir');")/blackfire.so \
    && printf "extension=blackfire.so\nblackfire.agent_socket=tcp://blackfire:8707\n" > $PHP_INI_DIR/conf.d/blackfire.ini \
    && rm -rf /tmp/blackfire /tmp/blackfire-probe.tar.gz

先ほどアカウントからコピってきたアカウントのIDやTOKENなどをdocker-compose.ymlの中に記述。

  blackfire:
    image: blackfire/blackfire
    environment:
        # Exposes BLACKFIRE_* environment variables from the host
        BLACKFIRE_SERVER_ID: {SERVER_ID}
        BLACKFIRE_SERVER_TOKEN: {SERVER_TOKEN}
        BLACKFIRE_CLIENT_ID: {CLIENT_ID}
        BLACKFIRE_CLIENT_TOKEN: {CLIENT_TOKEN}

これで準備完了。

Blackfireの使い方

コンテナ内部でインストールは終了しているのであとは計測するだけ。
自分が計測したいエンドポイント(https://hogehoge.jp/api/~) をブラウザ側で開きます。

開いたら、BlackfireのChromeの拡張機能をクリック。すると「Profile」ボタンが出てくるので
クリック。

計測が始まるので待ちます。

終わると全体の速度とレスポンスサイズが出力されます。詳細をみたい場合は「View Call Graph」をクリックする。

すると全体像がグラフ化されて、処理のフローを見ることができます。
上位はLaravelのデフォルトで呼び出されるやつですね。

  • 右のグラフ
    • フローチャートっぽく、この順番で処理が呼び出されてるでーってことを可視化したのもの
  • 左のグラフ
    • 実際に一個の処理に何分かかっていて、割合これだけ取ってるでーってことを可視化したもの

Laravelの処理は一旦置いておいて、自分がロジック書いた部分を探してみる....
いや、このgetDaというメソッドに6秒もかかってるやんけ!
この計測時間の下の矢印部分。これが6秒かかってる内訳。この矢印のボタンの幅が大きければ大きいほど、その処理の中で時間を食い潰している割合が大きいことになります。

ただのGETリクエストに4秒...🤔????(GuzzleはHTTPリクエストなどを行うライブラリ)
みたいな感じで、処理のどこが遅くなっているのか把握することができます。(たまにLaravelのKarnel処理だけで1.5秒くらいかかってるのが気になる

結論:Blackfireは結構便利

これを知らない間は計測処理などを入れていて都度確認していました。
https://qiita.com/dublog/items/0647c306afc835efbeb5

確実に遅くなっている場所がわかっているのであればこれでいいんですが、全体像としてどこが遅いのか把握しておきたい時に処理の数が多ければ多いほど把握は難しくなっていきます。
ですが、このツールを使えば一眼でどこがどう遅いのか把握できるので個人的にはまじで便利です。