Oct 2, 2005

MT 3.2でrecently_commented_onとBerkeleyDBに嵌っている人が多い件について

MT 3.2日本語版がリリースされてすでにインストールしている人も多いかと思いますが、嵌っている人も多いようです。代表的には以下の二種類の嵌り方をしている人が多いみたいです。

  1. 小粋空間: 3.2-ja 再構築時のパフォーマンス
  2. ちはろぐ: 「Movable Type 3.2 日本語版の提供を開始」らしいけど......(2005年09月29日)

このエントリーはこの2つの問題に対して解答を与えるためのものです。

念のため、BerkeleyDBをObjectDriverに使うくらいなら最初からSQLiteを使った方がずっと幸せになれる(というかまだBerkeleyDBを使ってたのか、捨てちまえ)とご忠告申し上げます。

recently_commented_onに関わる問題

あまり言及されていませんが、MT 3.1以前と3.2ではrecently_commented_onの仕様が異なっています(ソースコードが「公開された仕様」であると信じるならば)。

注: さらにMT 3.2-ja-2では、BerkeleyDB, SQLite, MySQLでは従来とおり、Postgresではここに書いたとおりの振る舞いをするように変更されています。訳が分かりませんが、前者の3つのDBエンジンを使用している場合には、recently_commented_onをlastn, daysオプションを一緒に指定すると無視されるので気をつけましょう。

3.1以前では、recently_commented_onはlastnやdaysオプションと一緒に指定することはできませんでしたが、3.2ではできます。つまり、以前はすべてのエントリーを対象に最近コメントされたエントリーをリストアップする機能でしたが、3.2では指定された範囲のエントリーを対象に最近コメントされたエントリーをリストアップする機能となりました。

多少機能が強化されたわけですが、メモリの消費量と速度に影響があります。具体的には指定された範囲のMT::Entryオブジェクトをすべてメモリ上に読み込んだ後、それら個々のエントリーに付けられた最終コメント時刻の降順にソートし、recently_commented_onオプションで指定した数だけ先頭から取り出すということを行います。lastnなどで範囲指定することなく使用すると、上記の操作がすべてのエントリーを対象に行われることになります。したがって、なるべくlastn, daysと併用するようにすることです。

また、これとは別にMT::Entry->comment_latestでやたらメモリを消費するという、BerkeleyDB特有の問題もあります。いかにも循環参照とか起きていそうで嫌な感じです。後で述べるパッチではこの問題を「回避」するコード修正を含みます。この修正によって(recently_commented_onに関しては)ほぼ許容可能なメモリ消費と速度で動作するはずです。

BerkeleyDBを使っていてMTEntryNextなどが正常に動作しない問題

日本語版β2でなされた変更で、「同日時のエントリーが複数あった場合に、エントリーの編集画面で『前のエントリー/次のエントリー』が正しく動作しない」という問題への修正がありました。これはつまり、同一日時のエントリーの順番をエントリーのIDを使って決める、という修正がなされたわけです。このこと自体はリーズナブルですね。

さて、同一日時のエントリーが4つあり、そのIDが1, 5, 9, 10だったとします。ID=5のエントリーの「次のエントリー」を決定するには、ID=5と同一時刻に作成された1, 9, 10のうち、5より大きい最小のものを選択することになります。逆に「前のエントリー」を決定するには5より小さい最大のものを選択することになります。このためには一般にエントリー群をIDに関してソートできなくてはなりません。

ところでMTのBerkeleyDB用のObjectDriverには古くからマイナーながら知られたバグがあって、対象オブジェクトをIDに関してソートして指定個数取り出すことができません(他のフィールドに関してソートすることはできる)。が、lib/MT/Entry.pmのsub _nextprevにはそのようなコードが記述されています。これではMTEntryPrevious/Nextや(同じロジックを用いる)エントリーの編集画面の『前のエントリー/次のエントリー』が正しく動作するはずがありません。

要するに、このバグを真っ当に修正するか何らかのwork aroundを用意する必要があります。実は同じ問題がlib/MT/Comment.pmとlib/MT/TBPing.pmにもあります。下で述べるパッチはwork aroundコードを挿入するものです。その後真っ当に修正する方法を思いついたのでパッチはそのように変更されています。

パッチ

説明はともかく以下のパッチを参照のこと。

dbm_flaw-comment_latest.patch

どうもパッチのあて方が分からないという人が多いみたいなので説明しておきます。
  1. Linux/FreeBSDなどではpatchコマンドがありますが、Windowsなどには標準では入っていません。Cygwinをインストールするなり、Programmers' toolboxからWindows版GNU Patchをゲットしておく必要があります。
  2. パッチファイルをMT 3.2日本語を展開したディレクトリに置きます。
  3. コマンドラインで「patch -p0 < パッチファイル名」と実行します。

2005-10-02 15:47追記: 以前のパッチにミスがありました。すでに適用した方は再度やり直してください。

2005-10-02 19:20追記: さらにrecently_commented_onを使用してもメモリ使用量が増大しないように対処しました。多分完璧です。

2005-10-03 16:06追記: たびたび申し訳ない。Entry.pm, Comment.pm, TBPing.pmに回避コードを入れるのは止めにして、DBM.pmを修正しました。この方が修正が圧倒的に少なくて済みます。

2005-10-04 00:35追記: さらに申し訳ない。MT 3.2ではDBからロードしたオブジェクトをキャッシュしておくようになっていて、それためメモリの使用量が3.1以前より大きくなっています。ところで、MySQLなどの場合にはこのキャッシュを一定個数以上作らないようにad hocなGarbage Collectionが行われるのに対し、BerkeleyDBの場合には作りっぱなしになっています。新しいパッチではMySQLなどと同様Garbage Collectionを行うように修正を加えています。

2005-10-05 11:40追記: 若干修正。Six Apartから何らかの正式な対策が用意される予定です(Six Apart - MovableType News: Berkeley DBの環境下でMovable Type 3.2日本語版をご利用のお客様へのお知らせ)。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

Copyright 2012 Ogawa::Buzz | Powered by Blogger
Design by Web2feel | Blogger Template by NewBloggerThemes.com