いつの頃からか、自分のサイトがクソ重たいと感じるようになり、知人などからも「重いよね?」「見れなくない?」などの苦情を頂いておりましたが、そのうち直そうと思っておりました。
このサイトはXreaというレンタルサーバを使っています。一番安いプランを使っているので、同じIPアドレスに300サイトぐらいが詰め込まれている状況です。〔参考:Reverse IP Check〕
2009/2頃には逆引きネームサーバのうんたらかんたらという大規模障害が発生し、しばらくアクセスできない状態が続いたり、かと思えば三分ぐらい経つとページが表示されたりと、普段このサイトを見てくれている人には大変ストレスフルな状態が続いていました。
直そうとは思っていたんですが、縦書きプロジェクトの進捗が芳しくないことと、原因がわからないまま「サーバ変えて終わり!」というのが性に合わないので、今日の今日まで移転の決断が遅れてしまいました。
あと、ユーザ激減という事態が普通にヤベーなと思ったこともありますです、はい。土日になると三分の一ぐらいに減っちゃうんですよね~。普通は逆なのに。
というわけで、このエントリーでは結論とそれにいたる経緯についてでも書こうと思います。
結論
Xreaを解約して、さくらサーバへ移転。
悪いのは外部Webサービスの多用とその実装方法でした。
1.サーバスペックの検証
まず、このサイトで表れた症状というのは、「ページが表示されない」です。
普通、リンクをクリックするなり、特定のページへアクセスしようとすると、ブラウザに「読み込み中」みたいな表示が出て、アドレス入力欄に該当するページのURIが表示されますね。それからページが表示されます。
が、このサイトへアクセスしようとすると、この「読み込み中」がいつまでたっても変わらないんですね。
これは「Javascriptが重い」とか、「画像データが巨大」とか、そういった問題ではなく、そもそもHTMLファイルが出力されていないわけです。したがって、ページの表層ではなく、サーバ側の問題なのではないかなとあたりをつけました。
で、実施したのがこのテスト。
<?php //関数実施前のタイムスタンプを取得 $start = microtime(true); for($i=0;$i<=100000;$i++){ $num++; } //関数実施後のタイムスタンプを取得 $end = microtime(true); //時間差を出力 echo $end - $start; ?>
テストというほど大層なもんではございませんが、これでサーバ(で動くPHP)の性能をある程度見ることができます。
で、このテストを自分の家のPCと、Xreaのサーバ、そしてさくらインターネットのお試しサーバでやったんですが、あんまり変わらない。ということは、PHP自体の実行速度は問題じゃない。
次に疑ったのが、データベースI/O。WordPressはデータベースへの接続があるので、ここがボトルネックになっていることも考えられます。
そこで今度はこんなテスト。
<?php //関数実施前のタイムスタンプを取得 $start = microtime(true); //テスト環境とサーバ環境でのDB接続情報を定義 if($_SERVER["DOCUMENT_ROOT"] == "C:/xampp/htdocs"): define('DB_NAME', 'dbname'); define('DB_USER', 'dbuser'); define('DB_PASSWORD', '******'); define('DB_HOST', 'hostname'); $table_prefix = 'wp_'; else: define('DB_NAME', 'dbname'); define('DB_USER', 'dbuser'); define('DB_PASSWORD', '******'); define('DB_HOST', 'hostname'); $table_prefix = 'wp_'; endif; //データベースに接続 $conn = mysql_connect(DB_HOST,DB_USER,DB_PASSWORD); mysql_select_db(DB_NAME,$conn); //データベースから10万回データを取得 for($i=0;$i<100000;$i++){ mysql_query("SELECT * FROM ".$table_prefix."posts LIMIT 1",$conn); } mysql_close($conn); //関数実行後のタイムスタンプを取得 $end = microtime(true); //実行前後の時間差を出力 echo $end - $start; ?>
で、これまたあんまり変わらないんですね。取得するフィールドの数が増えれば時間もかかるんですが、1個や2個のフィールドならさくっと表示します。うーむ。
2.WordPressの検証
で、Xreaはそんなに悪くないんじゃないかと思い、今度はWordPressを疑ってみました。僕はWP大好きっ子なので、よく仕事などで「やっぱり企業はMTじゃないと」などと言われると、「なにを!」と思っていたりするんですが、サーバとの相性でパフォーマンスが落ちるということもあるのかな、と疑ってみた次第です。
でも、膨大にあるWordPressの関数を紐解くのは面倒すぎるので、Xdebugで試してみました。
Xdebugというのは、PHPerならよく知っているデバッグツールです。関数ごとの実行時間などを教えてくれます。Y-110’s Wikiさんで詳しく紹介されています。
が、これまた大して時間かかってないんですねえ… ということは、WordPressの構造にも問題はないわけです。
3.プラグインの検証
とりあえず、さくらのスタンダードプランを借りてみて、WordPressを丸ごと上げてみました。と、時間はかかるものの、1分ぐらいで表示。Xreaだと3分ぐらいかかっていました。
だったらもう、プラグインを手当たり次第に当たっていくしかない! といいつつ、すでに怪しいんじゃないかと思っていたのがこちら。
- Twitter Tools :いちいちついったーにリクエストしてるっぽいから。
- Skype online status :いちいちskypeにリクエストしてるっぽいから。
- wp-tmkm-Amazon :いちいちAmazonにリクエストしてるっぽいから。
- Ultimate Google Analytics :毎回全文解析してリンク入れてるっぽいから。
ちなみに、上記のほとんどが外部WebサービスAPIを利用しているもの。file_get_contents()とか、curl()とか使ってるんじゃないでしょうか。
Twitter toolsなんかはDBにキャッシュを残すという律儀な仕様になっているのですが、それでも最新つぶやきのチェックぐらいはしているはずなので、「よその サーバにデータをもらいに行く」という行為がボトルネックであることにはかわりありません。PHPの段階でこれをやられると、相手の都合で処理を止めることになりますからね。
で、全部外してみたところ、HAEEEEEE! ってぐらいすぐに表示されました。これでしたよ。
Xreaだと1分、さくらなら数秒で表示されました。GoogleアドセンスとAmazonアフィリエイトのところでもガクッと表示が止まるので、やっぱりこれです。
Javascriptの場合はユーザとついったー、PHPの場合はたぶんXreaとついったーの間が高速かどうかという問題に還元されるかと思うのですが、どちらにせよ、Webサービスを提供している側のサーバはかなりあっぷあっぷなんでしょうね。ちゃんと負荷分散はしていると思いますが。
Xrea+よりさくらスタンダードプランの方が上位サービスなんで、早いのは当たり前なんですが、外部通信のネットワークI/OでXreaの分が悪いようです。あくまで推測ですが。
とはいえ、サーバ移転&プラグイン削除で済むかというと、そうもいきません。投稿内に残った大量のショートコードを削ることはできないので……wp-tmkm-Amazonなんかはもうサポートしないみたいだすし。自分でなんとかするしかないですね。
元のプラグインを残しつつ、Ajaxでの書き込みに変えるとか、サーバにキャッシュを残すとか……
まとめ.今後WordPressプラグインはどうあるべきか?
今回当たり前といえば当たり前の結果が出たんですが、自分が今プラグインを作っている最中ということもあり、なかなか考えさせられました。
WordPressのプラグインは数多ありますが、中にはきちんと考えて作られていないものもあります。無償でやるレベルの仕事だと、外部Webサービスを取得して表示するぐらいでも結構大変ですからね。
じゃあ、Ajaxにして非同期にしたら解決すんのかというと、色んな人が書いたJavascriptが飛び交うサイトというのも危険なわけでして。style=”display:none;” ってところで関数の衝突が起きたら終わりです。そもそも「テーマを自由に選べる」という最大の魅力が、JavascriptのDOM操作に対して危険な障壁になるんじゃないでしょうか。
キャッシュに残す仕組みだって、結構技術がいりますからね。「キャッシュできないならWebサービスのプラグイン作るな!」という文化だと、昨日今日PHPをいじり始めた人がプラグイン作って「楽し~い!」ということがなくなってしまいますし。
というわけで、WordPress本体にがんばってもらい、Ajaxやキャッシュについてのガイドラインも生まれると嬉しいなっと思います。
ちなみに、現在作成中のWp-Tategakiですが、そもそもXMLリクエストが必要ないという結論にいたり、基本構造から作り直しています。Javascriptにページコンテンツの内容を引っこ抜かせて、Flashに渡すという形式にしました。正規表現でくじけそうですが、もうちょっとでαリリースできそうです。