Nucleus

キャッシングプラグインの機能計画書

2006年4月2日

 一番の特徴としては、スキン変数としてプラグインを使用すること。ほとんどの設定は、スキン変数のパラメータとして記述する計画。キャッシュしたデータは圧縮保存して、サイズをなるべく小さくする。

(この記事は、仕様が変わり次第随時変更)

0)一般的なこと。
・基本的にメンバーログイン時は、キャッシュしない。
・SQL テーブルを作成して、キャッシュ内容(ファイル名等)を管理。
・目標としては、このプラグインのオプション設定は無しで、すべてスキン変数で管理する形にする。
・ほとんどのケースでデフォルトのまま使用できるようにしたい。

1)アイテムごとの違いの認定(コメントも含む) <%gzCache(item)%>
 item 追加・編集→PostMoveItem, PostAddItem, PostUpdateItem, PostDeleteItem, PrepareItemForEdit, PostAddComment, PreUpdateComment, PostDeleteComment(変更が在れば、該当キャッシュファイルを削除) PrepareItemForEditは日付の変更に伴う、アーカイブ表示の対応に必要。
グローバル変数 $itemid のチェックで、どのアイテムが表示されたかをトラックし、SQLテーブルに記述。

2)アイテム一覧表示 <%gzCache(index)%>
 グローバル変数 $archive をチェック。設定がなければ、どの item が変更された時でもキャッシュを廃棄(この場合、carchive=-1)。(未来の日付で投稿されたアイテムは、どうしようか?→day オプションが使用できる)
 グローバル変数 $archive が設定されていた場合、当該月・当該日の変更があったかどうかをPostMoveItem, PostAddItem, PostUpdateItem, PostAddComment, PreUpdateComment, PostDeleteCommentでチェック。変化が有ればキャッシュを破棄。
 ファイル名に、グローバル変数 $_GET の各値を含むようにするか?(下で述べる、プラグインオプションのファイル名プレフィックスを参照)

2.5)ファイルプリフィックス指定 <%gzCache(filename,cache-$_GET)%>
 下記の、スキンの種類ごとのファイルプリフィックス指定に関わらず、ファイル名を強制的に指定。

3)プラグインオプション変更の認定 <%gzCache(plugin,pluginName)%>
 プラグインオプションの変更→PostPluginOptionsUpdate(変更が在れば、該当キャッシュファイルを削除)
スキン変数オプションに従って、SQLテーブルに記述。

4)データベーステーブル変更の認定 <%gzCache(db,tableName)%>
 SQL クエリーによるチェック。カルマ投票・トラックバックなど。(どうやって、テーブル内容をチェックする?md5 でも使うか?)スキンパース後にチェック。変化が有れば、当該キャッシュをすべて破棄。
スキン変数オプションに従って、SQLテーブルに記述。
 もし、データベースのすべてのデータに依存する md5 値を計算するとすると、どれぐらいの時間がかかるのだろうか?(下記・テーブルのチェック法を参照)


5)日付による違い。 <%gzCache(day)%>
 カレンダーなどで使用。
キャッシュした日付は、キャッシュファイルの作成日時から得られるが、SQLテーブルにも記述しておく。このスキン変数呼び出し時にチェック。変化が有れば、当該キャッシュをすべて破棄。

6)メンバーログイン時のキャッシュ使用 <%gzCache(loggedin)%>
 この場合、キャッシュされたデータは使用するが、キャッシュへの保存はしない(セキュリティーのため)。カテゴリー表示などに使用。

7)スキン変更の認識
 PostDeleteSkinでスキンが削除された場合、当該キャッシュを削除。また、スキンファイルと、スキンの内容の変化を md5 でフォロー。

8)データベースと、キャッシュファイルの整合性。
 プラグイン管理画面が表示された時、整合性をチェックし、余分なデータ・キャッシュファイルを削除。

9)事前チェックが必要な物。
 スキンファイル(incファイルなど)。(追記:FTPなどを用いた時は、管理者が一度ブログを閲覧することにすれば、事後チェックでよいはず。)

10)事後チェックでよいもの。
 データベースに依存する物(phpmyadmin等は使わないという前提で)。イベントは、PostSkinParse, AdminPrePageFoot を用いる。従って、Nucleus ver 2.5 以降に対応。

・SQLテーブル

$query='CREATE TABLE IF NOT EXISTS `'.sql_table('plug_ncache').'` ('
    ."`cskinid` int(11) NOT NULL DEFAULT '1',"
    ."`cskintype` varchar(32) NOT NULL DEFAULT 'index',"
    ."`cfilename` varchar(128) NOT NULL DEFAULT '',"
    ."`ctime` datetime NOT NULL DEFAULT '1970-01-01 00:00:00',"
    ."`citemid` int(11),"
    ."`carchive` varchar(10),"
    ."`cplugins` varchar(128),"
    ."`cdb` varchar(128),"
    ."`cdbchecksum` char(32),"
    ."`cinterval` char(1),"
    ."PRIMARY KEY (`cfilename`)"
    .") TYPE=MyISAM;";

$query='CREATE TABLE IF NOT EXISTS `'.sql_table('plug_ncache_skin').'` ('
    ."`cskinid` int(11) NOT NULL DEFAULT '1',"
    ."`cskintype` varchar(32) NOT NULL DEFAULT 'index',"
    ."`cskinchecksum` char(32),"
    ."PRIMARY KEY (`cskinid`,`cskintype`)"
    .") TYPE=MyISAM;";


・プラグインオプション

1)キャッシュデータを格納するディレクトリ(デフォルトは、nucleus/plugins/gzcache/cache)
2)スキンタイプごとの、ファイル名プレフィックスの命名ルール(例:"itemcache-$itemid")。このプレフィックスに、スキン変数として何回目に現れるかの数を追加し、ファイル名とする。

・テーブルのチェック法

データベースのすべてのデータを md5 でチェックするルーチンのたたき台
$tables=array();
$checksums='';
$ret=mysql_query("SHOW TABLE STATUS LIKE '".sql_table('%')."'");
while ($a=mysql_fetch_assoc($ret)) array_push($tables,$a['Name']);
$mt=time()+microtime();
foreach($tables as $table) {
    $fields=array();
    $ret=mysql_query("SHOW FIELDS FROM $table");
    while ($a=mysql_fetch_assoc($ret)) array_push($fields,$a['Field']);
    $query='';
    foreach($fields as $value) {
        if ($query) $query.=",MD5(`$value`)";
        else $query="SELECT CONCAT(MD5(`$value`)";
    }
    $query.=") AS checksums FROM $table";
    $ret=mysql_query($query);
    while ($a=mysql_fetch_assoc($ret)) $checksums.=$a['checksums'];
}
echo md5($checksums)."\n";
echo time()+microtime()-$mt;
このルーチンで、すべてのデータをチェックしても、所要時間は0.1秒ほど(サーバクロック 300 MHz)。`nucleus_member` 等の小さなテーブルだけなら2ミリ秒ほどだから、スピード的にはほぼよさそう。(追記:ラクーカン+SQLite だと'nucleus_member'だけで0.2秒、すべてのデータを調査すると3秒で、かなり遅い。再考すべし。)(追記:パース後に調査する形にすれば、スピードの問題は関係ないか?)

・スキンファイルの調査

デフォルトスキンの md5 値をチェックするルーチン
$mt=time()+microtime();
echo md5(checkDir($DIR_SKINS.'default'))."\n";
echo time()+microtime()-$mt;
function checkDir($dir) {
    $dir=str_replace('\\','/',$dir);
    if (substr($dir,-1)!='/') $dir.='/';
    $d = dir($dir);
    $ret='';
    while (false !== ($entry = $d->read())) {
        if ($entry=='.'||$entry=='..') continue;
        if (is_file($dir.$entry)) $ret.=md5_file($dir.$entry);
        else if (is_dir($dir.$entry)) $ret.=checkDir($dir.$entry);
    }
    $d->close();
    return $ret;
}
ラクーカンで、ブログの表ページを表示するのに3秒かかる環境で、平均0.02秒で調査できる。まあまあのスピードか?(参考:FTP アップロードなどでスキンが変化する可能性があるため、この調査はパース前に行う必要有り。)

(ver 0.15 現在のマニュアル)
NP_gzCache 改め NP_nCache(nano/nest の n)

スキンの記載方法:
<%nCache(begin,param,param ... )%>
<%if(blogsetting,nCache)%>

something here

<%endif%>
<%nCache(end)%>

 パラメータ(『param』)は複数記載可能。次の通り

1) filename, file name
 デフォルトのファイル名プレフィックス以外のファイル名プレフィックスを指定する時に使用。『$catid』などのグローバル変数を使用することもできる→例:『category-$catid-$subcatid』
2) index
 アイテムの一覧表示を行わせる時に使用。アーカイブ表示などにも対応している。表示アイテムのどれかに変更があった時に、キャッシュが破棄される。各アイテムへのコメントに変更があった時も、キャッシュを破棄。
3) item
 個別アイテム表示の際に使用。当該アイテムに変更があった時に、キャッシュが破棄される。アイテムへのコメントに変更があった時も、キャッシュを破棄。
4) categorylist
 カテゴリーリストの表示の際に使用。いかなるアイテムの変化でも、キャッシュが破棄される。また、カテゴリ名変更などでも、キャッシュを破棄。
5) plugin, plugin name
 プラグインオプションを変更した時に、キャッシュを破棄。
6) db, database table name
 MySQL データベースに変化があった時に、キャッシュを破棄。例:『db,plug_multiple_categories』
7) month | day | hour
 月・日または時間が変わった時に、キャッシュを破棄。
8) loggedin
 ログインしている時でも、キャッシュされた内容を表示。新たなキャッシングはしない。

 スキンの記載は、入れ子にすることも可能。ただし、親のパラメータ記述は、子のパラメータ記述のすべてを含んでいる必要有り。

 スキンに変化があった時は、該当スキンに関するキャッシュはすべて破棄される。FTP などで inc ファイルをアップロードした際などでも、キャッシュの破棄が起こる。ただし、FTP を用いた時は、一度で良いからサイトを閲覧・もしくは管理ページに入ること。

 基本的に、ログイン中はキャッシュされない。ただし、パラメータに loggedin を指定すると、キャッシュされた内容の表示はできる。

 プラグインオプション編集画面で、キャッシュをオフにしたり、すべてのキャッシュの破棄をしたりすることが可能。また、キャッシュの最大サイズを指定可能。

追加予定の機能
1)requestVar (あるいは、$_GET['xxx'])の値の、キャッシュファイル名への取込を可能にする設定。
<%nCache(var,requestVar,varName)%>
<%nCache(var,intRequestVar,varName)%>
<%nCache(var,cookieVar,varName)%>
等。eval()関数を用いて、グローバル関数を直接呼び出す形にする。

2)カスタムオプションの設定。
<%nCache(custom,customName,param1,param2,....)%>

コメント

コメントはありません

コメント送信