ほんじゃーねっと

おっさんがやせたがったり食べたがったりする日常エッセイ

PHP製のWebアプリが遅い場合の基本チェック6点

先日別のチームから、

「PHPで作成したWebアプリの速度が遅いので助けてくれー」

という相談を受けた。

対応したものの、結構時間がかかって面倒だったので、

今後こういった問題が起こった時に使えるよう、チェックリストをまとめてやった。

基本的な内容だけど、 このチェックリストの内容をやってみて、それでもダメなら相談しなさい、 と伝えておくことで相談を減らすフィルタとして働いてくれるはずだ。

PHPプロジェクトに限らず、バックエンドでデータベースを使用している Webアプリのプロジェクトなら試す価値のあるものが多いはず。

調査や対応方法の手軽さ順で並べるとこんな感じ:

  1. Webブラウザのデベロッパーツールでレスポンスを計測する
  2. Webサーバ(Apache)のリクエスト時間をログに出力する
  3. ログ解析ツールでURL毎の付随リクエスト数を確認する
  4. データベースのスロークエリログを出力する
  5. プロファイラを使用してサーバ側アプリ内での関数毎の処理時間を計測する
  6. PHP(or使用言語)やフレームワークのバージョンを上げる

Webブラウザのデベロッパーツールでレスポンスを計測する

最近のメジャーなブラウザ(Internet Explorer、Firefox、Chrome)は デベロッパーツール(開発向けツール)が搭載されており、今開いているサイトについての情報を色々と確認することができる。 Web制作をしているとJavascriptやリンク切れエラーが出てないか確認したりソースチェックしたり、結構お世話になるツールだ。

例えばChrome(他のブラウザはよく知らない)の場合、 このデベロッパーツールの「Network」のタブを開いた状態でチェックしたいページを開くと、 そのページを開く際にどんなリクエストが走っているのか、それぞれのファイルや画像のレスポンスに サーバ側とクライアント側でどれだけ時間がかかっているのかがズラズラーッと表示される。

これをチェックするだけで、 サーバ側の処理に時間がかかっているのか、 それともサーバからブラウザへの転送に時間がかかっているのか、 はたまたブラウザでレスポンスを受け取ってからページを生成するのに時間がかかっているのか、 ということが確認できるので、次にサーバ側を調査すべきなのか、クライアント側(Javascriptとか画像の提供方法とか)を 調査すべきなのかが分かる。

ここでクライアント側が遅いと分かったら、近くのJavascriptプログラマに相談して、 使っているライブラリが悪いのか、Javascriptの処理が悪いのかを相談するといい。 (なぜならこれ以降はサーバ側の問題についてしか書いていないから!)

それぞれのブラウザの開発者向けツールの説明サイトを記載しておく。

Chromeの場合:

Evaluating network performance - Google Chrome

Internet Explorerの場合:

Internet Explorer 開発者ツールを理解する

Firefoxの場合:

developer.mozilla.org

Webサーバ(Apache)のリクエスト処理時間をログに出力する

Apacheのログ設定を変更することでリクエストごとの処理時間をログに出力することができる。

やってることは上のブラウザでのレスポンスチェックと同じようなことだが、 Apache側で勝手にログを残してくれるので、例えば画面によって遅かったり速かったりする、 という時にどのURLで問題が起こっているのかを把握するのに使えるはずだ。

Apacheのhttpd.confのログ出力設定で「%D」」というオプションを追加すると、 そのリクエストの処理にかかったマイクロ秒数が出力されるようになる。

Apacheのログ設定の詳細について知りたい場合は下記のマニュアルが詳しい:

mod_log_config - Apache HTTP Server Version 2.2

ログ解析ツールでURL毎の付随リクエスト数を確認する

ここでいうログ解析ツールというのは、Apacheのログを分析して色々な角度で集計してくれるようなツールのことだ。

Windows向けだとApache Log Viewerが無料でメジャーでおすすめ:

www.vector.co.jp

レスポンスが遅い時の理由としてよくあるのが、 フレームワーク等の設定をミスっててページを開く度に不要な画像、CSS、JSファイルのリクエストを大量に流してるとか、 やたらリダイレクトしてるとか、 ボットが大量にアクセスしてきてるとか、 何かしらの原因でWebサーバが高負荷な状態を繰り返しているような場合。

こういったログ解析ツールを使うと怪しいリクエストが発見しやすくなり、 何がWebサーバに負荷を与えているのかが把握しやすくなる。

データベースのスロークエリログを出力する

個人的な経験として、Webアプリが遅い時はデータベースの処理で時間がかかっている場合が多い気がする。

ここまでのチェックで特に怪しいリクエストが大量発生しているわけではなく、 リクエストは少ないのに1つ1つのリクエストで時間がかかっている、ということが分かったらデータベース処理を疑ってみよう。

ただ闇雲に使っているSQLをチェックしていっても時間がかかるだけなので、 メジャーなDBMSには大抵ついてる「スロークエリログ出力機能」を使おう。 これは指定した時間以上かかったクエリをログに出力してくれる機能だ。

開発時やテスト時からスロークエリを出力するようにしておいて、 インデックスが効いてないクエリが走るようになっていないか、ログで確認できるようにしておこう。

MySQLとPostgreSQLは下記のサイトで設定方法が確認できる:

MySQLの場合:

MySQL :: MySQL 5.5 Reference Manual :: 5.2.5 The Slow Query Log

PostgreSQLの場合:

PostgreSQL: Documentation: 9.4: Error Reporting and Logging

ちょっと分かりにくいけど、「log_min_duration_statement」オプションを使う。

プロファイラを使用してサーバ側アプリ内での関数毎の処理時間を計測する

これについては言語によって用意されているものとされていないもの、意味合いが異なるものあるかもしれない。

PHPの場合はプロファイラ処理をサーバ側プログラムに埋め込んでおくことで、 リクエスト毎にどの関数が呼び出され、その処理にどれだけ時間がかかったかを記録して HTMLページとして結果を確認できるなかなか便利なものが公開されている。

これらのツールを使うと、自作のプログラムだけでなくフレームワークやライブラリ、 データベースアクセス処理も含めてどこで時間がかかっているかを確認することができるので、 サーバ側アプリにパフォーマンスの原因がある場合はかなり有効な手段だと思う。

私はよくXhprofを使う。

Xhprofのマニュアル:

PHP: Xhprof - Manual

Xdebugというツールもある:

Xdebug: Documentation

使ったことはないがBlackfire Profilerというのもある:

blackfire.io

PHP(or使用言語)やフレームワークのバージョンを上げる

これを試すのは匙を投げる直前。バージョンを上げることで逆に問題が増えることの方が多いだろうし、 まだまだスケジュールに余裕があるぜ、という場合や、最新版を使っているつもりが誤って古いバージョンを使っていた、 みたいな場合じゃなければ選択すべきではない。

ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

ハイパフォーマンスWebサイト ―高速サイトを実現する14のルール

  • 作者: Steve Souders,スティーブサウダーズ,武舎広幸,福地太郎,武舎るみ
  • 出版社/メーカー: オライリージャパン
  • 発売日: 2008/04/11
  • メディア: 大型本
  • 購入: 32人 クリック: 676回
  • この商品を含むブログ (127件) を見る