mod_ruby で画像変換

動機

mod_ktai等でちと話題にあがっているapacheレベルでの動的な動画作成。ゆめみさんがなかなか出してくれなさそう(残念ながらソース非公開っぽいし)&Cなんて書けないし書く気もしない。のでmod_rubyの検証も兼ねつつ、ちゃらっといけそうかどうかをテストがてらに確認してみる。

問題点

RMagickにはメモリリークがある(らしい)。

試行錯誤。

http://www.kaeruspoon.net/articles/402
こちらのページを参考にテストしてみるが1リクエスト毎に子プロセスを立ち上げることのオーバーヘッドが大きすぎ。


http://rubyforge.org/forum/forum.php?thread_id=1374&forum_id=1618
こちらの情報だともうライブラリレベルで対応ができてるっぽいので実装してみる。いい感じで動きそう。

テストコード

mod_rubyのソースです

require "cgi"
require "rubygems"
require "RMagick"

r = Apache.request
r.content_type = "image/jpeg"
r.headers_out.add("Expires",CGI.rfc1123_date(Time.now + 3600))
r.send_http_header()

img = Magick::ImageList.new("/cluster/wdc/test/92/164/202/210.qvga.jpg")
r.puts(img.resize(320, 240).to_blob)
img.destroy!
img = nil 
fDisabled = GC.enable
GC.start
GC.disable if fDisabled

テスト

私の開発環境のメモリが非常に寂しいものなので同時アクセスは控えめにテストを行う。いちおうRMagickのメモリリークがテストのポイントなんでまぁよしとしよう。

テストコマンド

ab -c 10 -n 20000 http://***/***.rbx

テスト結果

Server Software:        Apache/2.2.9
Server Hostname:        192.168.100.78
Server Port:            80

Document Path:          /cgi-bin/test.rbx
Document Length:        18222 bytes

Concurrency Level:      10
Time taken for tests:   1643.192533 seconds
Complete requests:      20000
Failed requests:        0
Write errors:           0
Total transferred:      368600000 bytes
HTML transferred:       364440000 bytes
Requests per second:    12.17 [#/sec] (mean)
Time per request:       821.596 [ms] (mean)
Time per request:       82.160 [ms] (mean, across all concurrent requests)
Transfer rate:          219.06 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    1   7.6      1     917
Processing:    69  819 1263.9    412   44342
Waiting:       67  796 1225.6    408   44341
Total:         70  820 1264.0    413   44343

Percentage of the requests served within a certain time (ms)
  50%    413
  66%    490
  75%    565
  80%    798
  90%   2221
  95%   3246
  98%   4651
  99%   5970
 100%  44343 (longest request)

TOPで眺めている分にはメモリリークは発生していなさそう。
longest request はちと気になる・・・・。

結果

速くはないねぇ。。。ちなみに、同一環境でRailsの2.1のDB接続ありなシンプルなページをproductionモードでパフォーマンステストしてみると30req/secぐらいでるのかな。
でも、apacheのfilter等を使ってCで実装したところでImageMagickの画像変換のオーバーヘッドは避けられないんじゃないかな。と考えると、Cでがんばって書くだけのメリットは見いだせなさそう。実際はmod_cacheと組み合わせて使うんでこの結果で何とかなると思うし。将来的によりけちくさい(高尚な)レベルでパフォーマンスを云々するときはうちの偉い人に書き直してもらえばいいんだしまずはこの方向でOKかな(投げっぱなし結論)。

蛇足

変換前画像のチョイスと、変換後サイズ指定をもうちょっと考えてテストすればよかった。。。。もう面倒なんでやらんけど。