おおいしつかさ


旅行とバイクとドライブと料理と宇宙が好き。
Ubie Discoveryのプログラマ。
Share:  このエントリーをはてなブックマークに追加

RMagickのメモリばか喰いを解決する方法

 大量の画像ファイルを、それぞれいくつかのサイズのサムネイル画像を作りつつ、それぞれをDBにも保存しなければならない、という処理が必要になったのですが、RMagickのメモリ消費の阿呆さ加減にやられてしまいました。とにかく一切メモリ解放をしてないんじゃないかと思ってしまうくらいのすこさで、topコマンドで見るのが怖いくらいなのです。
 で、ネットで情報を探ってみると、まあ当然というかGCをループの終わりでやれと書いてある。しかも、GC自体が無効になっている可能性も考慮して、

  fDisabled = GC.enable  
  GC.start  
  GC.disable if fDisabled  

こんなことをやれとあちらこちらに書いてある。で、試してみたのだけど、確かにメモリ消費の加速度は鈍った。鈍ったのだけど、やっぱりやがては限界までメモリを食い尽くしてプロセスが異常終了してしまう。さらに毎回GCが強制的に走るので、処理速度も若干遅くなった。今回は、処理速度も重要な要点のひとつなので、なかなか大変なのだ。

 で、考えたのだけど、メモリ消費が限界に達する前にそのプロセスを終了して、続きを別プロセスではじめればいいのでは? と思ったのでやってみた。

file_names = (すべての画像ファイルの名前を持つ配列)  

until file_names.empty?  
  files = file_names.slice!(0..999)  
  pid = fork do  
    files.each do |file|  
      (RMagickの処理)  
    end  
  end  
  t = Process.detach(pid)  
  t.join  
end  

で、topコマンドの画面を見ながら実行してみると、1000ファイル単位でメモリが解放されていた。素晴らしい。