再び動的・静的な議論やMTチューニングな話です。
- 続・静的生成と動的生成、Webページをビルドするコストは誰が支払うべきなのか (talk to oneself 2)
- [N] Movable Typeの再構築を少し高速化するチューニング
- MovableTypeの高速化と動的・静的な話 (blog@browncat.org)
前置き。トラックバック・コメントスパムの負荷に関して
トラックバックスパムは当サイトでは.htaccessでIPアドレスとUserAgentでフィルタをしています。レンタルサーバによっては使えないかもしれませんが、MTやWPにたどり着く前に拒否するので効果的です。当方ではこれでスパムの大半(90%以上)はカット出来ていて、残りもほぼジャンクフィルタに引っかかります。全体的に負荷が減り、スロットリングも起こりにくくなっています。標準のスパムフィルタだけではスロットリングや負荷増加は避けられませんので、UAのフィルタだけでもお試し下さい。
本題の前置き
さて、静的、動的な話ですが、まあ結局は規模や用途や好みに応じて使い分けというのが結論的な気もしますが、それでは面白くないのでもう少し考察。
まず基本的に私の考えとしては、こういった高速化のコストはシステム提供者と管理者がまず払うべきだと思っています。ここではMovableTypeやWordPressのシステムそのものがまず第一。次に管理を行う人。これは記事のライターとかぶることも多いとは思いますが。
WordPressの場合は動的システムなので手段としてはキャッシュ、phpの最適化ツールでしょうか。MovableTypeの場合はオーバヘッドを減らすFastCGIや生成過程を最適化することで高速化されるはずです。
WordPressではやはりキャッシュかな?
WordPress内蔵のキャッシュはさほど効果ありませんが、プラグインのWP-Cacheは優れものです。極力早い段階で動作するよう設計されており、一旦構築したページは再度作ることなく返すことが出来るためphpを経由するとはいえ非常に高速です。
またapacheのmod_cacheはクライアントのキャッシュと同じ判断でキャッシュを行う方式で、php呼び出しはもちろん実際のファイルすら読まずにページを返すことが出来ます。組み合わせるとメモリやディスクは食いますが、時々発生する動的ページ生成を除き、静的なページとほぼ同等の性能となると考えられます。
注意するべき点はスラッシングというキャッシュ容量を超えたアクセスが常時来る場合で、WP-Cacheはおそらく大丈夫ですが、mod_cacheの場合キャッシュ溢れが起こりっぱなしだと性能が逆に低下する可能性があります。 特に大規模サイトだと調整が必要かもしれません。
WP-Cacheプラグイン設置もapacheのmod_cacheを有効にするのも簡単です。MTのテンプレートを改造するより楽ではないかと思います。(mod_cacheは環境により使用できないかもですが、MTにも有効かもしれません)
後出来ることといえばxcache, eAccelerator, ZendOptimizer等の中間コードキャッシュ、最適化ソフトを使ってphpをなるべく高速化するというあたりでしょうか。
MovableTypeを最適化できないかな?
さて、MovableTypeですが、SixApartさんも再構築を高速化するためにいろいろ改良をされていると思いますが、やはり時間がかかるのは事実です。何とか高速化したいものです。
エントリのファイルがない状態でアクセスされたらその時点で動的生成を行おうという実装をされています。素晴らしいです。これは基本的にキャッシュ管理を静的に行おうという発想で生成後のペナルティは0。非常に効率の高い方法ですね。さくっと作られたのには頭が下がります。私としては別な方向から、再構築自体の高速化を考えてみると、MovableTypeの個別エントリの構築を多パスにして、最初に決めることが出来るものを事前に処理、中間的なテンプレートを作成。これを使って全エントリを再構築することでかなりの高速化が図れそうな気がします。
ネタフルさんではMTIncludeで分割したりMTBlogURL等をテンプレート修正で固定文字列に変えて高速化されたとのことですが、本来このコストはMovableType側が負うべきコストではないかと思うわけです。
エントリを書いた後に野田さんから頂いたトラックバックのエントリです。私の説明が悪かったのですが、こちらで行われているような高速化ノウハウ部分というのは全てではないにせよ機械的に判断できるものも多いはずなので自動化出来ないかな?という考えです。
最適化の流れをもう少し詳しく書くと
もう少し詳しく説明すると、例えば個別エントリ生成時に、'最近のエントリー'の処理やMTBlogURLの展開は最初に一回だけ行なうだけでいいはずで、通常人手でテンプレートを分割したりしているものもMovableTypeからみれば、どのタグが個別エントリに影響するか判断できるわけです。そこで
- 1パス目:再構築過程全体で一回だけ走り個別エントリに関連するタグ(MTEntryPermalinkや関連するIf系など)を除いた全てのタグを処理。個別エントリ向けのタグは残った状態のテンプレートを生成
- 2パス目:1パス目の結果を使って普通に全エントリを生成する。そうすれば個別エントリで変化する部分以外は全て展開済みの状態で処理出来るため高速
なのではないかと思ったのです。もちろん人手でテンプレートを分けた方が速いかも知れませんが、近い速度にはなると思います。
これを現状のシステムをなるべくそのまま使って実現出来ないかと考え、少し安易ですが以下のようにすればいけるのではないかと。
- 個別エントリのテンプレートをインデックステンプレートとして登録
- そのインデックステンプレートからの生成ファイルを個別エントリのテンプレートとして登録
- 個別エントリ用のインデックステンプレートを前処理して個別エントリに影響するMTタグを別名に置換(XMTxxx等という感じ)
- インデックス生成(この時点でMTBlogURLなどは解決済みとなる)
- 2の結果を後処理してMTタグに戻す
- これを個別エントリのテンプレートとする
- 全エントリ生成
最初は操作上人手をある程度介しても良いので、試しにやってみようとソースコードを見てみましたが、まだ良くわかっていません。外部のスクリプトで処理するなら何とかなりそうですが、いずれにせよ不慣れなもので少し時間がかかりそうです。最終的な使い勝手的には通常の再構築とあまり変わらずに出来ればベストではないかと。
以上まずは案だけなのですが、既に誰かがやられている気もするので、情報いただければうれしいです。
まだ暫定的ですが、こんな感じで実現できそうです。
おまけですが、perlccでmt.cgiをバイトコードコンパイルしたら心持ち速くなった気がします。これから使ってみて安定動作するか見てみます。