キャッシュの効果が出やすい/出にくいモジュール(その1)

小粋空間様で、以下のような記事がアップされていました。

藤本さんの記事に触発されて、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.続きは後日

まだ他に書くべきことがありますが、記事が長くなってきましたので、続きは後日とさせていただきます。