Q4M のベンチマークと設計

Re: http://mt.endeworks.jp/d-6/2008/01/q4m-1.html dmaki さんありがとうございます。

  • やっぱり Mac OS X の F_FULLFSYNC は遅いなぁ
    • 同期方法をバイナリ配布版の InnoDB の手法に合わせるかな
      • ソース版はデフォルトだと fsync
    • でも dmaki さんの速度はさすがに遅すぎな気もする (自分のとこだと倍くらい)
      • ディスクがいっぱいいっぱいなのかなw
  • 宣伝になるような実際の利用形態にあったベンチマークを同梱しておいたほうがいいかも
    • キューは普通、サブスクライバを複数並べて使うものだし
      • 処理がすぐ終わるんだったら直接 InnoDB テーブルに書けばいい
    • というわけで t/05-multireader.t 追加
      • race condition のバグが見つかったので、それようのテストコードも兼ねてるw


で、↓が宣伝用ベンチマーク。make test したらこんな感じで表示されるようになりました。

[kazuho@KazMac:~/dev/q4m]$ DBI='dbi:mysql:database=test;hostname=kazmac;port=3307' make test
perl -MTest::Harness -e 'runtests(@ARGV)' t/*.t
t/01-base...........ok                                                       
t/02-queue..........ok                                                       
t/03-queue-error....ok                                                       
t/04-blob...........ok                                                       
t/05-multireader....ok 1/4                                                   

Multireader benchmark result:
    Number of messages: 6400
    Number of readers:  32
    Elapsed:            11.909 seconds
    Throughput:         537.412 mess./sec.

t/05-multireader....ok                                                       
All tests successful.
Files=5, Tests=5356, 291 wallclock secs (95.11 cusr + 15.79 csys = 110.90 CPU)

ちなみにこの値は手元の MacBook (Core 2 Duo @ 2GHz) で --with-sync=fcntl (つまり F_FULLFSYNC) を使った場合。いやらしく表にまとめてみる。

環境 スループット (メッセージ/秒)
Mac OS X 10.4 (Core 2 Duo @ 2GHz, --with-sync=fcntl) 537.412
Mac OS X 10.4 (Core 2 Duo @ 2GHz, --with-sync=fsync) 2503.643
Linux 2.6.18 (Pentium 4 @ 3GHz, hdparm -W 0) 1083.244
Linux 2.6.18 (Pentium 4 @ 3GHz, hdparm -W 1) 1322.701


つぎに

うーん、queue_wait()にWHERE使えると嬉しいなぁ・・・

について。どういうことなのかなぁ、と、しばし悩んだ。Q4M の場合、基本的に以下のように考えています。

  • 1テーブル=1送信先
    • 送信先が複数ある場合は、その数だけテーブルを作ればよい
      • 送信先が動的に増減することはない
    • そのほうが処理的にも速くなる
    • てかディスクベースのバイナリツリー実装なんかやりたくな〜い

ただ言われてみて思ったのは、送信先以外の条件を満たすメッセージを取り出したいこともあるのかもしれないということ。たとえば、メールの再送信処理やクローラの再取得処理等では、次回の処理開始時刻をカラムに格納しておいて、その時間になったらキューから取り出せるようになる、というような仕組みがほしいかも。

そういうことなんでしょうか? あるいは、他のユースケースで、テーブルの増設では対応しにくいものがあるようでしたら、教えていただければ幸いです。

あと queue_wait() が現状 0 を返した場合に NON-OWNER MODE のままなのを OWNER MODE にしておくべきかなと思った。そうしないと queue_wait() の返値のチェックが必須になるわけで。README のサンプルコードですらチェックしてないのにorz