比較しているのはよくある適当な 1080 x 236 px の JPEG 画像を ImageMagick を使って適当な位置を切り取ってくるという処理をして速度を比較しています。
比較したのは以下の3つ。
- MiniMagick
- ファイル渡しで ImageMagick を直接叩く
- パイプ渡しで ImageMagick を直接叩く
ベンチマークのスクリプト
require 'benchmark'
require 'mini_magick'
require 'tempfile'
require 'open3'
TARGET = 'common_case_1.jpg'
N = 1000
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
Benchmark.bm(20) do |x|
x.report('minimagick:') { N.times { minimagick } }
x.report('imagemagick_file:') { N.times { imagemagick_file } }
x.report('imagemagick_pipe:') { N.times { imagemagick_pipe } }
end
結果
user system total real
minimagick: 0.910000 2.490000 30.950000 ( 33.037064)
imagemagick_file: 0.300000 1.470000 26.260000 ( 27.954511)
imagemagick_pipe: 0.590000 1.420000 24.920000 ( 25.720133)
子プロセス分での処理をなんだかうまく表示できないのでわかりづらいが total から user + system 引いた分。
パイプ渡しで叩くのが早いっぽい。
考察
結局 ImageMagick 内での処理が一番かかり、ファイルの読み書きで速度が大幅に低下しているというわけではないようにみえるが、ファイルの読み書きをなくせばある程度は早くなる。JPEG の処理が一番処理を食うのであろうことが想像される。