WordPressチューニング: ボトルネックの調査

1カ月ぶりにブログを更新したら、ページ表示の遅さが気になってしまったので、今まで何もしてこなかったWordPressのパフォーマンス・チューニングを行うことにした。

WordPressチューニングの情報はWebにいろいろあるけれど、ほとんどが「この設定をこうしたらこんなに速くなった!」みたいな話ばかりで、パフォーマンス・エンジニアの端くれとしては「なんでそこがボトルネックだと判断したの?」という視点がないことが気になった。そこで、この記事では原因分析から評価まできちんと記しておこうと思う。ただ、Webアプリケーション・パフォーマンス・チューニングのプロではないので、その辺はお手柔らかに……。

以下ではHTTPサーバーに Apache HTTP Server 2.2.3 + CentOS 5.7、データーベース・サーバーに MySQL Community Edition 5.1.52 + Scientific Linux 6.1 を使っているが、その他の環境でも応用できるだろう。

まず、どこで時間がかかっているのかの切り分けを行おう。Google Chrome 15 のメニュー「ツール > デベロッパー ツール」を開き、Networkタブを表示したら、Shiftキーを押しながら再読み込みボタンを押してWebブラウザーのキャッシュを使わずに再読み込みする。何度か試してみると4秒弱という結果が最頻値のようなので、以下の結果で分析することにした。

index.phpの結果

タイムラインを見ると、一番上のindex.php (/blog/) に1.83秒と最も時間がかかっている。特にindex.phpのwaitingが終わらないとそのほかのファイル読み込みも全く始まらないので、これが1.83秒もあるというのは何とかすべきだ。index.phpのwaitingに時間がかかっている理由は大きく分けると「ネットワークのレスポンスが悪い」「HTTPサーバーのレスポンスが悪い」「動的ページ生成が遅い」の3つが考えられるだろう。

とりあえず動的ページ生成が遅いのかどうかの切り分けのために、同じページの静的ページを作成する。Google Chrome のメニュー「名前を付けてページを保存…」でHTMLのみをtest.htmlとして保存し、動的に生成されるindex.phpの静的ページ版を作成する。このtest.htmlをindex.phpと同じ階層に置いて、今度はtest.htmlにWebブラウザーからアクセスしてみる。

test.htmlの結果

index.phpに比べてtest.htmlの読込みが圧倒的に速い。つまり、動的生成に時間がかかっているということになる。動的生成が遅い理由は「PHPが遅い」「MySQLが遅い」の2つが考えられるので、そのどちらであるかを切り分けることにした。index.phpのチューニングにターゲットを絞ったので、Google Chrome のデベロッパーツールではなく、ab (Apache HTTP server benchmark tool) をここからは使うことにする。abはhttpd.rpmに含まれており、同じネットワーク内の別サーバーから実行した。

今のところ同時実行性は気にしないので-c (concurrentcy) は小さめで、1分程度負荷がかかるように-n (requests) を調整してindex.phpに対して実行した。以下がその結果であるが、Requests per second が0.56#/secということで、1秒間に1ページも応答できていないという結果となった。

このときのHTTPサーバー上で実行したdstatとiostatの結果をグラフ化したものが以下だ。CPUが100%使用されている。

CPU使用率 | HTTPサーバー

ディスク使用率 | HTTPサーバー

同様にデーターベース・サーバー上で実行したdstatとiostatの結果をグラフ化したものが以下だ。このデータベースはWordPress専用ではないにもかかわらず、CPU / ディスクともほとんど負荷はかかっていない。

CPU使用率 | DBサーバー

ディスク使用率 | DBサーバー

データベースのワークロードはほぼSELECTなので、ロック待ちなどでDBサーバーのリソースが使えていない可能性は低いし、仮にそうであればHTTPサーバー側も待たされてリソースを使えないはずだろう。これによりボトルネックはMySQLではなく、PHPであると考えられる。ここから「PHPエンジン」「WordPressコード」のどちらが遅いのかを切り分けることもできるが、たとえばWordPressのコードをチューニングするとその後のメンテナンスが面倒なので、この2つは総合的に考えることにした。

合わせてtest.html(静的ページ)にも同様にabを実行しておく。そのままでは計測時間が短すぎたので-nを増やしている。test.htmlの Requests per second が204.13#/secなので、動的ページ生成を最大限までチューニングすればこの値になるということで、逆に言うと動的ページ生成のチューニングだけではこれより良い値にはならないということだ。よって、今回のチューニング目標はこれより1桁小さい20#/sec(現行の35.71倍)とした。

このような「ボトルネックの特定」と「ゴールの設定」はパフォーマンス・チューニングにとって非常に重要で、これがチューニングの半分である。次回は実際のチューニングの一環として、APC (Alternative PHP Cache)を導入する。

One thought on “WordPressチューニング: ボトルネックの調査”

コメントを残す