Posted at

MiniMagick とか ImageMagick 使うときのメモリ消費量比較

More than 3 years have passed since last update.

http://qiita.com/overleo@github/items/516cdf7d882ded88fd76

これの続きです。

1日百万回ぐらい実行されるアプリでパフォーマンスが出ず、問題はメモリ消費量では、ということで調査しました。

前回と同様、よくある適当な 1080 x 236 px の JPEG 画像を ImageMagick を使って適当な位置を切り取ってくるという処理をして速度を比較しています。

比較したのは以下の3つ。


  • MiniMagick

  • ファイル渡しで ImageMagick を直接叩く

  • パイプ渡しで ImageMagick を直接叩く


環境

% ruby --version

ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]

スクリーンショット 2015-01-22 18.46.14.png


比較方法

ps を叩いて ruby プロセスがどれだけメモリを消費しているかを出力します。対象は ruby だけなので ImageMagick の使用分は含まれてない、はず。(子プロセスは毎回終了されるのでここでは考慮しないでも平気だろう、という感じ)

適宜 minimagick のところを入れ替えたり、GC.start をコメントアウトしたりしながら、1つ1つ全てのパターンを調査してます。

require 'benchmark'

require 'mini_magick'
require 'tempfile'
require 'open3'

TARGET = 'common_case_1.jpg'

N = 10000

IMAGE = File.open(TARGET).read

def minimagick
piece_image = MiniMagick::Image.read(IMAGE)
piece_image.crop('450x556+0+0')
image = piece_image.to_blob
end

def imagemagick_file
Tempfile.open('tmp_piece_input', './') do |input_image|
Tempfile.open('tmp_piece_output', './') do |output_image|
input_image.write IMAGE
`convert -crop 450x556+0+0 #{input_image.path} #{output_image.path}`
output_image.read
end
end
end

def imagemagick_pipe
image,_ = Open3.capture2("convert -crop 450x556+0+0 jpeg:- jpeg:-", stdin_data: IMAGE, binmode: true)
end

def put_memory_size
puts `ps -o rss= -p #{Process.pid}`.to_i
end

counter = 0
N.times {
minimagick
put_memory_size
if (counter += 1) > 100
#GC.start
counter = 0
end
}


結果

スクリーンショット 2015-01-22 19.15.30.png

縦軸はメモリ使用量、横軸はループ回数。

MiniMagick のメモリ使用量すごい。でもその前に自分で GC するの大切、という結果です。


さらに GC のタイミングを変えて比較した結果

スクリーンショット 2015-01-22 19.15.44.png

軸は先程と同様、10, 100, 1000 は GC.start するループの回数。10000 は自然に実行されるのに任せたもの。


考察


  • 適当なタイミングで自前で GC 実行しないとヤバイ、GC 実行されるタイミングでってあまり詳しくないですが画像のように大量にメモリが必要な物を大量に回すにはなんか考えないと