This repo aims to demonstrate the performance of ruby-vips, the Ruby binding for the libvips library, when used with the CarrierWave
file uploader plugin for Ruby on Rails framework.
There is similar repository, vips-benchmarks, which focuses on the advantages ruby-vips has over other image processing libraries. This repo is intended to show, how these advantages spread to Rails territory.
This benchmark uses the carrierwave-vips gem written by Jeremy Nicoll, other participants are modules which are currently used in carrierwave master branch.
Last update: May 24, 2013
$ bundle exec ./runner removing previous files uploaded by carrierwave... Linux mm-jcupitt2 3.5.0-21-generic #32-Ubuntu SMP Tue Dec 11 18:51:59 UTC 2012 x86_64 x86_64 x86_64 GNU/Linux This is RMagick 2.13.1 ($Date: 2009/12/20 02:33:33 $) Copyright (C) 2009 by Timothy P. Hunter Built with ImageMagick 6.7.7-10 2012-08-17 Q16 http://www.imagemagick.org Built for ruby 1.9.3 Web page: http://rmagick.rubyforge.org Email: rmagick@rubyforge.org MiniMagick 3.4 Ruby-vips 0.3.5 built against libvips 7.30.7-Tue Jan 15 11:40:02 GMT 2013 Timing (fastest wall-clock time of 3 runs): ruby-vips, jpeg image: 56ms rmagick, jpeg image: 166ms mini_magick, jpeg image: 348ms ruby-vips, png image: 1849ms rmagick, png image: 13105ms mini_magick, png image: 13445ms Peak memuse (max of sum of mmap and brk, excluding sub-processes): vips ... 60 MB mini-magick ... 62 MB rmagick ... 195 MB
Memory use is measured by watching strace output for brk and mmap calls, see Tim Starling's blog post.
We've timed for a 1024 x 768 JPEG image and a 5120 x 3840 PNG image.
JPEG images can be shrunk very quickly by subsampling during load, so we wanted to include a PNG as well to stress the memory systems on these libraries a little more.
MiniMagick does all processing in a forked mogrify
command, so its direct memory use for image processing is zero. Looking at top
, mogrify is is using about 150mb on this machine.
Darwin Stanislaws-MacBook-Air.local 11.4.2 Darwin Kernel Version 11.4.2:
Thu Aug 23 16:25:48 PDT 2012; root:xnu-1699.32.7~1/RELEASE_X86_64 x86_64
This is RMagick 2.13.2 ($Date: 2009/12/20 02:33:33 $) Copyright (C) 2009
by Timothy P. Hunter
Built with ImageMagick 6.8.0-10 2013-03-03 Q16
http://www.imagemagick.org
Built for ruby 1.9.3
Web page: http://rmagick.rubyforge.org
Email: rmagick@rubyforge.org
MiniMagick 3.4
Ruby-vips 0.3.5 built against libvips 7.32.1-Fri May 24 01:10:57 EEST
2013
Timing (fastest wall-clock time of 3 runs):
ruby-vips, jpeg image: 109ms
ruby-vips, png image: 1595ms
rmagick, jpeg image: 179ms
rmagick, png image: 6290ms
mini_magick, jpeg image: 540ms
mini_magick, png image: 6189ms
This machine has a faster CPU and has an SSD rather than a mechanical hard disc, but has a much slower jpeg decoder.
A similar procedure is run using each uploader. Each uploader is being run in its own file.
require 'benchmark' def image src File.open src end module Procedure NUMBER = 1 class << self def run processor, img, best_of result = nil capture_stdout do result = Benchmark.bmbm do |b| (1 .. best_of).each do |number| b.report number.to_s do NUMBER.times do u = User.new :name => 'first' u.send :"#{processor}_avatar=", img u.save! end end end end end output result end def output result result = (result.map(&:to_a).map{|el| el[5]}.min * 1000).to_i puts "#{result}ms" end end end
require 'active_record' ActiveRecord::Base.establish_connection( :adapter => 'sqlite3', :database => ':memory:' ) ActiveRecord::Schema.define do create_table :users, :force => true do |t| t.integer :name t.string :rmagick_avatar t.string :mini_magick_avatar t.string :vips_avatar end end
Besides uploading original file, each uploader has 3 versions to generate. Let's take one of them for example:
# encoding: utf-8 class RMagickUploader < CarrierWave::Uploader::Base # Include RMagick or MiniMagick support: include CarrierWave::RMagick # include CarrierWave::MiniMagick # include CarrierWave::Uploader::Processing # include CarrierWave::Vips version :rtlimit do process :resize_to_limit => [100, 100] end version :rtfit do process :resize_to_fit => [100, 100] end version :rtfill do process :resize_to_fill => [100, 100] end # Other stuff end
require 'app/uploaders/rmagick_uploader' require 'app/uploaders/mini_magick_uploader' require 'app/uploaders/vips_uploader' class User < ActiveRecord::Base mount_uploader :rmagick_avatar, RMagickUploader mount_uploader :mini_magick_avatar, MiniMagickUploader mount_uploader :vips_avatar, VipsUploader end
Run bundle
Runner running all sub-runners:
$ ./runner # or just $ rake
Runners for each of libraries:
$ ./runner-vips $ ./runner-rmagick $ ./runner-mini-magick
Feedback is appreciated!
Copyright (c) 2012 Stanislaw Pankevich, John Cupitt
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4