Hatena::ブログ(Diary)

diaの備忘録

2009年12月22日

RMagickでメモリリークが発生する

なぜメモリリークが発生するのか

そもそも、RubyにはGCがあるので自然に開放されるはずです。しかし、実際にはそうなっていません。これには下記のような理由があります。

RMagickはImageMagickのobj(mallocで確保した)を扱っていて、これはRubyのobjではありません。そのため、GCの対象にならず、メモリリークの危険性をはらむ事になります。


対策

対策1〜3の順でおすすめと思います。

対策1(RMagickとImageMagickのバージョン変更ができる場合)

RMagick 2.10.0で変更された下記に頼る。

  • (Experimental) Support the use of Ruby managed memory for all memory allocations (available in ImageMagick 6.5.3-10)
対策2(バージョン変更できない場合)

http://rubyforge.org/forum/forum.php?thread_id=1374&forum_id=1618にあるように、Magick::Image#destroy!を明示的に呼ぶ。

require 'RMagick'
include Magick

pics = Dir["*.jpg"]
pics.each do |pic|
  img = Image.read(pic).first
  # process new image
  img.destroy!
end
対策3(アーキテクチャ選定前)

競合製品を使ってみる。

MiniMagickの特徴

  • 薄いラッパー
    • ImageMagickのAPIを呼び出すだけ
    • なので、MiniMagickのドキュメントを覚える必要が無い
  • ImageMagickのobjを使用しない
    • なので、メモリリークが起こりえない
    • 代わりに処理のたびに一時ファイルを作成する
    • なので、遅い

MagickWandの特徴

  • RMagickの作者が作った
    • 作者曰く "RMagick rebooted."
    • 後発なので、今後はこちらが主流になる?

補足

メモリリークの検出には、Bleak House pluginが使いやすくておすすめです。