小粋空間様で、以下のような記事がアップされていました。
藤本さんの記事に触発されて、Movable Type 4.2 RC2 のモジュールキャッシュを試してみました。
私もこの記事に触発されて(笑)、キャッシュの効果が出やすい/出にくいモジュールについての考察を書いてみました。
1.データベースアクセスが多いモジュールほど効果が高い
テンプレートを再構築する際には、大まかに言えば以下のような処理が行われます。
- 再構築に必要なデータをデータベースから読み込む
- テンプレートを解析して、テンプレートタグをデータに置き換える
- 再構築結果をファイルに保存する
データベースからデータを読み込む際には、多数のファイルにアクセスします。
特に、多くのデータにアクセスするほど、アクセスするファイルの数も多くなり、処理に時間がかかるようになります。
ハードディスクはCPUの処理速度に比べるとかなり遅いので、データベースアクセスが大量に発生すると、処理にかなりの時間がかかってしまいます。
つまり、データベースアクセスが多く発生するテンプレートモジュールは、再構築を遅くする原因になります。
先日の「複雑なキャッシュとその効果」では、「記事と同一カテゴリに属する記事一覧」をキャッシュしました。
この処理も、記事ごとにデータベースアクセスが大量に発生します。
しかも、記事が増えるほど、データベースアクセスの量が増えます。
そのため、キャッシュすることで大きな効果が得られました。
一方、テンプレートの解析はメモリ上で行われる処理です。
よほど巨大なテンプレートなら別ですが、一般的なテンプレートであれば、処理にはさほど時間はかかりません。
また、再構築結果をファイルに保存する処理では、1ページにつき保存対象のファイルは1つです。
そのため、これも処理にはさほど時間はかかりません。
2.カウント系のタグは処理に時間がかかる
テンプレートタグの中には、オブジェクトの個数を出力するものがいくつかあります。
その一例として、ブログ内の記事数を出力するMTBlogEntryCountタグがあります。
カウントの際には、カウント対象のすべてのデータにアクセスするので、ディスクアクセスが大量に発生します。
このため、カウント系のタグは、処理に時間がかかります。
実験として、記事300件のテストブログを対象に、カテゴリアーカイブのウィジェットを使って、以下の3つのケースでブログ記事アーカイブの再構築時間を測定してみました。
| ケース | 内容 |
|---|---|
| ケース1 | カテゴリアーカイブのウィジェットをそのまま組み込む (カテゴリ一覧と、カテゴリごとの記事数を出力) |
| ケース2 | カテゴリアーカイブのウィジェットから、MTCategoryCountタグを除いたものを組み込む (カテゴリ一覧のみを出力) |
| ケース3 | カテゴリアーカイブのウィジェットを組み込まない |
すると、結果は以下のようになりました。
| ケース | 再構築の所要時間 |
|---|---|
| ケース1 | 89秒 |
| ケース2 | 54秒 |
| ケース3 | 40秒 |
ケース1とケース2の違いは、MTCategoryCountタグがあるかどうかですが、これだけで再構築の所要時間が35秒伸びています。
カテゴリアーカイブのウィジェットを組み込まなかった場合(ケース3)は40秒で処理が済んでいますので、その処理にほぼ匹敵する時間を、記事数のカウントに費やしていることが分かります。
しかも、このウィジェットはすべてのブログ記事ページに組み込まれます。
したがって、キャッシュして再構築回数を1回に抑えれば、大きな効果が得られます。
3.キャッシュの効果が出にくいモジュール
ここまでで述べたように、キャッシュの効果が出やすいのは、データベースアクセスが大量に発生するモジュールです。
逆に言えば、データベースアクセスが少ないモジュールだと、キャッシュの効果は薄くなります。
また、モジュールによってはデータベースアクセスがまったくないものもありますが、それだとキャッシュの効果もほぼ0です。
例えば、MT4.2の標準テンプレートセットの「バナーヘッダー」というモジュールを考えてみます。
このモジュールは、各ページのヘッダー部分(ブログ名やブログの概要など)を出力するもので、以下のような内容になっています。
<div id="header">
<div id="header-inner">
<div id="header-content">
<mt:ignore><!-- Use h1 and h2 html tags on the main index of the blog as the title, use divs on all other pages where there are page titles. --></mt:ignore>
<MTIf name="main_index">
<h1 id="header-name"><a href="<$MTBlogURL$>" accesskey="1"><$MTBlogName encode_html="1"$></a></h1>
<h2 id="header-description"><$MTBlogDescription$></h2>
<MTElse>
<div id="header-name"><a href="<$MTBlogURL$>" accesskey="1"><$MTBlogName encode_html="1"$></a></div>
<div id="header-description"><$MTBlogDescription$></div>
</MTIf>
</div>
</div>
</div>
このモジュールでは、ブログの情報を出力するために、MTBlog系のタグが入っています。
ただ、各ページを再構築する際には、MTBlog系のタグがあるかどうかに関係なく、ブログの情報をデータベースから読み込むようになっています。
したがって、上のモジュールをキャッシュするかどうかに関係なく、データベースアクセスの量は変化しない(はず)であり、キャッシュの効果は得られないと思われます。
実際、前述のケース3でこのモジュールをキャッシュしても、再構築の所要時間は40秒で、キャッシュしない場合と変化がありませんでした。
4.続きは後日
まだ他に書くべきことがありますが、記事が長くなってきましたので、続きは後日とさせていただきます。


コメントはスレッド表示になっています。
また、スレッドの先頭のコメントに対する返信には、先頭に矢印を表示しています。
はじめまして。モジュールと CGI テンプレートに関連する質問がありまして、コメントさせていただきました。
現在 MTOS 4.2 が正式版になったら新しくブログを作りたいなと思って準備作業中です。サーバーサイドインクルードで PHP を使い、キャッシュさせて共通部分を読み込ませる予定でおります。
その際、メールフォームプラグインなど CGI を利用するテンプレートでは、まあ案の定 PHP が読み込まれず、?php から始まるナマのコードが出力されます。メール送信確認テンプレートなど CGI で読み込むテンプレートには MTInclude を使わず、共通部分のソースをそのまま入力するしか無いのでしょうか?
なお MTOS 4.2rc2-ja 標準のコメント確認テンプレートや検索テンプレートなど、システム系のテンプレートに MTInclude の記述を追加した場合、そのまま普通に読み込むことができるようです。
メールフォームプラグインなどの各テンプレートでも MTInclude (以外でも構いませんが、何らかの手段) で読み込むことができればうれしいのですが、対処法などありましたらご教授いただけると助かります。
>ヤマガタ マヒルさん
こんにちは。
ご質問の件ですが、いくつか解決法が考えられます。
1.メールフォームをAjax化する
まず、メールフォームをAjax化して、フォーム部分のみをAjaxで切り替えて表示する方法があります。
2.MTIncludeタグに「ssi="0"」のモディファイアをつける
送信確認等のCGIで出力されるテンプレートでは、MTIncludeタグに「ssi="0"」のモディファイアを付けるようにします。
こうすると、サーバーサイドインクルードが無効化されます。
3.CGIの処理結果をPHPで再度処理する
コメント確認や検索結果のページの出力を、PHPで再度処理するスクリプトを公開しています。
同じ手法がメールフォームプラグインでも使えると思います。
以下のページを参照してください。
http://www.h-fj.com/blog/archives/2005/09/16-161205.php
<mtInclude module="モジュール名" ssi="0"> という記述を試してみましたが、出力結果に変化が無いようです。さくらスタンダード + SQLite + MTOS 4.2 という環境のせいでしょうか……?
ただ共通部品内で PHP を書きたいということもあり、別途ご教授いただきました CGI を PHP で再処理する方法を試してみようと思います。
素早い返信ありがとうございました。
ところで直接関係のない質問ですが……壱さんは、古い記事にコメントされた場合もチェックされておられますか? どの程度までなら古い記事に質問しても問題ないのか、ちょっと迷うときがありまして……。
>ヤマガタ マヒルさん
こんにちは。
>壱さんは、古い記事にコメントされた場合もチェックされておられますか?
記事の新しい/古いに関係なく、コメントがつくと自分宛にメールが送られてくるようにしていますので、古い記事にコメントしていただいても問題ありません。