4推測せずに計測してLaravelパフォーマンスチューニングPHPLaravelblackfireはじめにLaravelで開発した検索APIを、blackfireというプロファイラーを用いてパフォーマンスチューニングをしたので、その知見を共有します。https://blackfire.io/blackfireには有料プランが存在しますが、本記事で扱う内容は全て無料プランの範囲内です。いずれもドキュメントや先人の記事を参照してください。自力で見つけて下さい。本記事はそのヒントとなることを目指しています。画面左上の表示から、1.4sかかっていることが分かります。画面右のツリーを見て処理が重そうな箇所を探しましょう。route()改善前まず、MasterDatumViewModel::document()という関数が気になりました。これは検索結果のViewModelクラスで、検索結果1行ごとのURLを返すメソッドです。ソースコードを下記します。}この関数は検索結果の数だけ呼び出されます。1,000件検索では1,000回呼び出され、トータルで542msかかっています。これは全体の実行時間の40%弱を占め、そのほとんどがroute()呼び出しによるものです。1行ごとのURLが変わることは滅多にないので、検索結果のIDをキーに含めてキャッシュしてしまいましょう。}改善後のソースコードです。キャッシュドライバはmemcachedを使用しました。1.57sと、却って遅くなってしまいました。画面右のツリーを見ると、キャッシュリポジトリを取得するcache()とCacheManager::store()の呼び出しがかなりの割合を占めます。ViewModelクラスですし、インスタンス毎に異なるキャッシュリポジトリを使うことも考えにくいので、ここは思い切ってstatic変数にしてしまいましょう。}キャッシュリポジトリをstatic変数とし、クラス内で初回のみ取得するよう変更しました。結果は1.1sとなり、0.3sの高速化ができました。余談デプロイ時にはキャッシュを忘れずに削除しましょう。次に気になったのは、SearchMasterDataAdapter::findMasterData()という関数です。これは、入力された検索条件をクエリビルダーに適用し、検索結果をドメインモデルに変換して返すメソッドです。ソースコードを下記します。}この中で大きな比率を占めるのが$builder->get()です。ツリーを見ると、Eloquentが検索結果をMasterDataモデルにhydrateする処理に時間がかかっているようです。適切にデータがセットされたMasterDataモデルのtoDomainModel()さえ呼べれば用は足りるので、PDOで取得した検索結果をMasterDataモデルにセットしてみましょう。}まずはクエリビルダーをSQLとパラメータに変換して、PDOで取得します。それをMasterData::setRawAttributes()に渡すことでMasterDataモデルに値をセットし、ドメインモデルに変換します。先程の1.1sから、911msまで高速化できました。1,000件検索のプログラム改善はここまでとします。次はブラウザでAPI呼び出しを見てみましょう。1,000件ものデータとなるとその容量も小さくなく、433kbとなっています。その転送にはおよそ456msかかっています。これをWebサーバーで圧縮して、転送速度を改善しましょう。</IfModule></IfModule>コンテンツの圧縮の方法はここでは扱いませんが、Content-Typeがapplication/jsonで始まるレスポンスを圧縮するよう設定しました。charset=utf-8のようなケースで圧縮されません。)データ量が73.5kbまで低減しました。転送時間は大差ありませんが、これは開発環境がローカルであることが原因です。本番環境では転送時間が大きく改善していることを確認できました。次に1件検索時のプロファイルをします。1,000件検索時とは違って、もっとアプリケーションのベース部分の問題が判るはずです。サードパーティ製ライブラリ改善前1件検索時の結果は478msとなりました。この内、およそ50%程度をサードパーティ製ライブラリの処理が占めていました。ソースコードを読むと改善の余地が十分にありそうですが、vendor以下のコードを変更する訳にはいきません。ライブラリの修正を待つのも一つの手ですが、今回は時間的猶予がありませんでした。そのため、自分で改善したクラスをサービスコンテナに登録する形で対応しました。重要なのは、サービスコンテナを利用することで既存の処理も置換可能ということです。Laravelドキュメントのサービスコンテナのページを読んで下さい。https://readouble.com/laravel/6.x/ja/container.html284msとなり、およそ200msもの改善ができました。まとめ1,000件検索では1.4s→911ms。1件検索では478ms→284ms。本記事で行なった施策が、そのままあなたのプロジェクトに適用できることは稀だと思います。あなたのプロジェクトに最適な施策を見つけて下さい。推測するな、計測せよ。よきパフォーマンスチューニングを。upLoginユーザーは見つかりませんでした。