Jul 30, 2007

WebSig 24/7の参加報告 + MT4の高速化あれこれ

WebSig24/7というイベントに参加させていただいた。私の発表資料はそのうちどこかで公開されると思うが、私はMTOSとそれに関連してGPLまわりの話題を話させていただいた。

この手のイベントに参加するのは初めてなので、私ともあろう者が*1「空気読む」のに若干神経使ってしまった。あえてこの夏一番暑かっただろう日に、あえて東京の中でも緑化不足で無駄に気温の高い秋葉原に足を運んでくるという連中参加者がどういう種類の人たちなのかまるで分からなかったからだ。

*1 「空気を読まないし読もうともしない、そんな私が(常日頃にはあるまじき配慮をもって)」ということである。コメント欄のように体調を崩す読者もいらっしゃるようなので製造物に対する責任を果たすべく念のため註とした。

この際はっきり言わせてもらう、

「だいたいおまいらマジメ過ぎなんだよっ!!」

と。休憩10分だけで40分の講演を4本+質疑応答セッションを行うということの「非常識」を誰も認識していない。世間の標準というのは、20分講演+10分質疑のセットを4本まとめたくらいが1セッションで、そのセッションの合間には30分程度のブレークを入れるもんだ。まれに1セッションに6セットくらい詰め込まれると、参加者がぶーたれるか、4セット目あたりで自主的にブレークタイムに突入する参加者が現れるもんだ。参加者が大半がろくに話を聞いてなくてしょうがなく座長が無理矢理質問する、そのイタさ加減が「会議」の醍醐味ってもんなんだ。

「講演中に無駄口くらいしやがれ、内職しやがれ、内職してプラグインの一つも書きやがれ」

と私は言いたい。だけど、そういうマジメさも嫌いじゃないのでまた機会があったら呼んでください。ペコリ。

ついでなので、他の話者の話にツッコミを入れておこうと思ったけれど、私を含めてnot so technicalな内容だったので止めておく。それだけだとなんなので、再構築うぜぇからやっぱWordPressだよねっていうWeb屋は...いや、まぁ何だ、ちゃんと考えようぜ。 (Junnama Online (Mirror))にツッコミというか釣られてみる。

私がサクッと思いつく、高速化のアイディアとしては以下のようなものがある。

  1. 並列に実行する
  2. 高速なテンプレートエンジンを用いる
  3. データの局所性を利用する
  4. テンプレートを最適化する

まず、1.について。MT4の採用しているTheSchwartzやMemcachedを使った実装では、再構築を非同期に、かつ並列に行うことで高速化を達成できる。ただし、並列化の恩恵を受けられる環境を使える人は限られている。これはこれで高速化への解になっているのだが、シングルスレッドでの実行性能を追求することを先送りする解でもあって私のような最適化厨への受けは必ずしも良くない。

2.について。MTの場合、テンプレートを読み込み、パーズして内部的なデータ構造を作り、次にそのデータ構造を元にデータベースから必要なデータを読み込んで...(中略)...最終的にHTMLをレンダリングする、ということを行う。これを高速化するには、まあ安直に考えて以下の三つの方法がある。

  • MTの静的生成では、パーズ結果は毎回捨てられる。だからもし、その内容をキャッシュする機能を備えたテンプレートエンジンを作れば、解釈実行のオーバーヘッドは小さくできる。
  • また、MTの静的生成では、前処理部分はSyntax Treeのようなものを生成するだけでコンパイルせず(メソッド名はcompileだが)、後処理部分はSyntax Treeをトラバースしながら現れた変数タグ・コンテナタグに対応するハンドラメソッドをルックアップして実行している。簡単に言ってしまうとこれはテンプレート言語のインタプリタの実装である。この実装を捨ててしまい、コンパイルしてPerlプログラムを生成し、後処理ではそれをevalだけで済むようにすれば、解釈実行のオーバーヘッドを小さくできるし、コンパイル結果をキャッシュしやすくもなる。
  • また、MTのダイナミックパブリッシングでは、テンプレートのコンパイル結果(これはPHPプログラムになる)をキャッシュすることができる。だからもしコンパイル結果を解釈実行するコストがPerlとPHPで変わらないのだとすると、ダイナミックパブリッシングの方がオーバーヘッドが小さい。つまり、静的生成の時にもダイナミックパブリッシングのバックエンドをテンプレートエンジンとして使えば高速化できる。ただし、プラグインなどをPHPで書く必要があり、本質的な解にはならない。

3.に関して。2.に書いたような最適化ができたとしてもコンパイル済みテンプレートを解釈実行する際に、データベースを三三五五アクセスするのは効率が悪い。なぜなら、single-threaded codeの途中にシステムコールがあるとそれだけで遅くなるから。だから、テンプレートを解釈実行する前に使用するであろうデータの大部分をメモリ上にキャッシュしておき、それを再利用するようにすれば速くなる。ソフトウェアパイプライン的な最適化ね。

4.についてはjunnnamaさんが書いていることも部分的な解になっている。もう少し一般化すると、テンプレート「プログラム」の局所最適化を行うということ。例えば、プログラムの共通部分式を自動的に、あるいは人手を借りて検出することができれば、再計算を避けるためにキャッシュすることができる。この方法は、ターゲットプログラムが複雑であるほど困難だが、簡単なヒューリスティックで大きな効果が得られる場合も多い。

まあそんな感じ。あまり真面目に考えていないけど。

Jul 23, 2007

Ubuntuの設定メモは Wikiに分離しました

Ogawa::Buzz: Ubuntu 7.04日本語ローカライズ版の設定メモ (Emacs, TeX)
とか
Ogawa::Buzz: Ubuntu 7.04日本語ローカライズ版の設定メモ (USBハードディスク)
とかいう具合に一個一個エントリーを書くのは鬱陶しいのでTrac Wikiにまとめて書くことにしました。

UbuntuHowTo - ogawa - Google Code

私が微妙に嵌まったネタで、かつ解決したものしか載せないのでFAQとしては使えないと思いますけどね。

Jul 21, 2007

Ubuntu 7.04日本語ローカライズ版の設定メモ (USBハードディスク)

Ogawa::Buzz: Ubuntu 7.04日本語ローカライズ版の設定メモ (Emacs, TeX)の続き。

USBハードディスクをアンマウントできるようにする設定

USBハードディスクをUbuntu 7.04にアタッチすると自動的にマウントしてくれるのはいいのだが、アンマウントできない。デスクトップのハードディスクアイコンを右クリックして「イジェクト」すると、アンマウントされた後、再マウントされてしまう。CD-ROMドライブなどを前提とした振る舞いに見える。

/etc/hal/fdi/policy/preferences.fdiに以下の設定を加えて再起動すれば、以降は「イジェクト」の代わりに「アンマウント」できるようになる。

  <!-- 
    override /usr/share/hal/fdi/policy/10osvendor/10-storage-policy.fdi to be able to unmount
    USB harddrives.
  -->
  <device>
    <match key="info.category" string="storage">
      <match key="storage.bus" string="usb">
        <merge key="storage.requires_eject" type="bool">false</merge>
      </match>
      <match key="storage.bus" string="ieee1394">
        <merge key="storage.requires_eject" type="bool">false</merge>
      </match>
    </match>
  </device>

ちなみに/usr/share/hal/fdi/policy/10osvendor/10-storage-policy.fdiを削除してしまうことでも同等の効果がある。だが、/usr以下は変更せずに/etc以下の設定ファイルを使ってマシンローカルな設定を行うのが鉄則。

NTFSでフォーマットされたUSBハードディスクを読み書き可能にする

ntfs-3gを使えばよい。

$ sudo apt-get install ntfs-3g

Jul 14, 2007

Ubuntu 7.04日本語ローカライズ版の設定メモ (Emacs, TeX)

「日本語版セットアップ・ヘルパ」とか使うと裏で何が起きているのか分からなくなって右往左往してしまうold-fashionedな私がUbuntu 7.04日本語版の設定メモを書くよ。とりあえず今回はEmacsとTeX関係の設定だけ。

Emacsの設定

$ sudo apt-get install emacs-env-ja
$ cp /usr/share/doc/emacs-env-ja/dot.emacs.example ~/.emacs

.emacsは必要に応じて編集する。いつも通りでUbuntuだからと言って特記するようなことは何もない。

TeXの設定

UbuntuのTeX関係の情報はubuntu ptex - Google 検索で山ほど見つかる。こういう時、だいたい本来の「情報源」はそんなに多くはないはずなのだが、時間が経つに連れて情報が過度に集積されたり、情報が多い文献からの子引き・孫引きが増えたりする。これは知識の集積としては必ずしも有用とは言い難い。ものすごい数のパッケージをインストールすることを勧められ、よく分からないのでその通りにし、その結果として何が得られたのかさっぱり分からないということになりがちである。

初心に立ち返ってこう考えるべきである。「TeXを使って普通に文章を書いたりする分には、ptex/platex, jbibtex, xdvi, dvipsさえ使えればよい。それ以外のものは必要になったときに初めてインストールすればよい。」と。

であれば、これだけインストールすればよい。

$ sudo apt-get install ptex-bin jbibtex-bin xdvik-ja dvipsk-ja

Ghostscriptの設定

Ubuntu 7.04では、gs-espがデフォルトでインストールされているが、日本語がうまく表示できない。ちゃんと表示できるようにするには、まずいくつかのパッケージをインストールする。

$ sudo apt-get install gs-cjk-resource cmap-adobe-{japan1,japan2,cns1,gb1}

上を実行すると「/usr/bin/mkcfmがない」と怒られるはずだが無視していい。どうしても気になるなら前もって、

$ sudo ln -s /bin/true /usr/bin/mkcfm

とかしておけばよい。ちなみにmkcfm - Google 検索では、mkcfmがnon-freeであり、CentOSからコピって解決したよというページが山ほど出てくる。non-freeだと知ってやるならライセンス違反であるとの謗りを免れない。スピード違反をブログで喧伝するようなものだ。

次に、

$ sudo dpkg-reconfigure cmap-adobe-japan1

を実行して「随意」のところをチェックして「了解」しておく必要がある(どういう翻訳なんだろう)。

ともあれ、ちゃんと設定できていればgs-espでもevinceでも正しく表示されるはずである(evinceは内部的にgs-espを呼び出しているだけ)。

$ gs -sDEVICE=x11 hoge.ps
$ evince hoge.ps

evinceがあるので正直言って不要なのだが、どうしても必要ならgnome-gvとかも入れておく。

$ sudo apt-get install gnome-gv gv

ちなみにgnome-gvだけでもインストールできてしまう。gnome-gvはgvなしでは動かないからdependencyの定義がおかしい。

日本語を含むPDFを表示できるようにするための設定

日本語を含むPDFを閲覧できるようにするには、evinceを使う方法とAcrobat Readerを使う方法の2つがある。

前者は、

$ sudo apt-get install xpdf-japanese

後者は、

$ sudo apt-get install adobereader-jpn

とすればOK。前者の方が高速でメモリフットプリントもかなり小さい。ただし、微妙にフォントのメトリック情報がおかしい。

xdvi、ghostscriptでIPAモナーフォントを使うための設定

ubuntu ptex - Google 検索などを見ていると、/usr/share/fonts/truetype/kochiのシンボリックリンクを張り替えたりする泥縄的な解法が主流のようだが、そんな必要はない。Ubuntu(Debian)にはdefomaというスタティックにフォントのリンケージを管理する仕組みがあるので、それを使って東風フォントではなくIPAモナーフォントを選択するようにすればいいだけのことである。

まず、/etc/defoma/hints/ipamonafont.hintsをエディタなどを使って以下のように編集する。

category truetype
begin /usr/share/fonts/truetype/ipamona/ipag-mona.ttf
  Family = IPAMonaGothic
  (snip)
  Priority = 60
  Alias = GothicBBB-Medium
  (snip)
end
category truetype
begin /usr/share/fonts/truetype/ipamona/ipam-mona.ttf
  Family = IPAMonaMincho
  (snip)
  Priority = 60
  Alias = Ryumin-Light
  (snip)
end

要はipag-mona.ttfおよびipam-mona.ttfのPriorityの値を60にし(東風フォントのPriorityが50なのでそれより大きく設定する)、Aliasを加える。この設定を反映するためにさらに以下のコマンドを実行する。

$ sudo defoma-font reregister-all ipamonafont.hints
$ sudo update-vfontmap

あとはxdvi、evinceコマンドで動作確認する。今日はここまで。

Jul 13, 2007

メン募: mtos-jaグループ

2007年の第3四半期にリリースされる予定のオープンソース版Movable Typeについての日本語グループをGoogleグループに作りました。

mtos-ja | Google グループ

このグループが対象とするのは、

  • 「オープンソース化」に伴う技術的、非技術的な事柄についての相談
  • Movable Typeの使い方についての相談
  • Movable Typeを使ったサイト、プラグイン・ツールなどのアナウンス
  • Movable Typeの日本語コミュニティに関係ありそうなイベント、飲み会などのアナウンス
  • などなど

です。何でもありですが、特に以下のような話題については取り扱いません。

  • シックスアパート版のライセンスの運用に関わる話題(例: 個人無償ライセンスを使って商用サイトを運用できますか、など)
  • Movable Type Enterpriseの利用方法

お気軽にご利用ください。

Jul 3, 2007

RebuildQueue二題

RebuildQueue - mtplugins - Trac (Tracサイト。しょっちゅう落ちているので読めないことが多い。)
RebuildQueue README.txt

RebuildQueueは非常に便利なツールなのだが、(1) 英語でしかほとんど情報がない上Tracサイトもなかなかアクセスできず、(2) コマンドラインまたはcronで実行する必要があるという制約がある、せいかあまり使っているという話は身近に聞かない。

簡単に言うと、Movable Typeの再構築を2フェーズで行うツールである。第一フェーズは再構築するファイルとそのスペシフィケーションをリストしてデータベースに格納しておき、第二フェーズではその情報を使って実際の再構築を行う。つまり、MTのCMSで編集を行ったり、コメント・トラックバックを受信したりした場合には第一フェーズだけを実行し、第二フェーズはcronやデーモンを使って別プロセスで実行する。

肝は、

  1. 第一フェーズが軽量であること
  2. 第二フェーズは任意の時点で別プロセスで実行できること
  3. 第二フェーズは分散した複数のサーバで並列に実行できるのでより高速に再構築できること

である。3.に必要な実行環境を用意できる人は必ずしも多くないので効用は割り引いて考えなければならない。

で、ここからが本題。

本題一つ目。RebuildQueueはMovable Type 3.3以降で使えるが、4.0では使えない。Pronet MLで聞いたところによれば、RebuildQueueはコア機能に組み込まれる予定のようだ。beta4には組み込まれていないので本当のところどうなるのかは分からない。このあたりの事情をスルーして3.3でも4.0でも使えるようにしたRebuildQueueをでっち上げたので下においておく。

RebuildQueue-MT4

MT4ではMT::WeblogPublisherが大幅にrewriteされてリファクタリングされているので、MT4用にRebuildQueueを拡張するのは簡単な作業だった(ベンチマークをとっていないがおそらくMT3用のコードより高速なはず)。オリジナルとの差分はこれくらい(r383 - ogawa - Google Code)で済んでしまう。

本題二つ目。RebuildQueueの第二フェーズはcronやデーモンを使って別プロセスで実行する必要があると書いたが、実はちょっと工夫するとcronなどが使えない環境でも利用できる。

RebuildQueueRunner

RebuildQueueRunnerは、RebuildQueueの第一フェーズが実行されたタイミングでバックグラウンドプロセスを起動して第二フェーズを実行するプラグインである。第一フェーズが実行されるたびにバックグラウンドプロセスが起動されるのでは具合が悪いので、MT3.3が備えているタスクマネージャ機能を使って5分間に高々1個のバックグラウンドプロセスしか実行しないようにしてある。

RebuildQueueとRebuildQueueRunnerの組み合わせによって実現される機能は、実はJunnamaさんとこの

MovableType Background Rebuilder Plugin(1.0RC2)(1.0RC1). (Junnama Online (Mirror))

にかなり近い。私の実装の方が簡単で、MT4にRebuildQueueが組み込まれた場合にも容易に対応できるというメリットがあるが、Junnamaさんの実装の方が再構築の単位が細やかになっている。

RebuildQueue-MT4RebuildQueueRunnerとももう少し時間を割いてドキュメントを書きたいところなのだが時間がない。

About Me

My Photo

つくばで働く研究者

Total Pageviews

Amazon

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