Skip to content

Instantly share code, notes, and snippets.

@xunker
Created October 2, 2014 21:46
Show Gist options
  • Save xunker/06571aec238e0c54ca4d to your computer and use it in GitHub Desktop.
Save xunker/06571aec238e0c54ca4d to your computer and use it in GitHub Desktop.
Compare zipruby memory consumption with others
#!/user/bin/env ruby
#
# Demonstrates memory behaviour with zipruby vs rubyzip vs exec('unzip').
# Tested with mri 1.8.7/1.9.3/2.1.2, zipruby 0.3.6 and rubyzip 1.1.6.
#
# Usage: ruby zipruby_test.rb <test method>
#
# Test methods are:
# read_zipruby read file from zip using zipruby gem
# read_rubyzip read file from zip using rubyzip gem
# read_exec read files from zip using exec + unzip(1)
# data_times (sanity) populate var using String#* to size of test file
# data_append (sanity) populate var using String#<< to size of test file
#
# Code assumes you have unzip(1L), curl(1) and BSD-style ps(1).
#
# This script does an action 10,000 times, stopping every 1,000 times to
# record its own memory. At the end of the run it prints all 10 memory
# footprints in the order they were recorded.
#
# Results:
#
# read_zipruby
# ruby-1.8.7: 56K, 110K, 161K, 208K, 257K, 306K, 357K, 403K, 451K, 499K
# ruby-1.9.3: 60K, 112K, 167K, 214K, 262K, 312K, 362K, 409K, 456K, 506K
# ruby-2.1.2: 72K, 136K, 194K, 258K, 311K, 371K, 412K, 473K, 527K, 587K
#
# read_rubyzip
# ruby-1.8.7: requires >= 1.9.2
# ruby-1.9.3: 14K, 20K, 20K, 21K, 21K, 21K, 21K, 23K, 23K, 23K
# ruby-2.1.2: 21K, 26K, 27K, 27K, 28K, 28K, 30K, 30K, 30K, 30K
#
# read_exec
# ruby-1.8.7: 5K, 5K, 5K, 5K, 5K, 5K, 5K, 5K, 5K, 5K
# ruby-1.9.3: 7K, 8K, 8K, 8K, 8K, 8K, 8K, 8K, 8K, 8K
# ruby-2.1.2: 23K, 27K, 30K, 30K, 31K, 31K, 31K, 31K, 31K, 31K
#
# data_times
# ruby-1.8.7: 11K, 19K, 19K, 19K, 19K, 19K, 19K, 19K, 27K, 27K
# ruby-1.9.3: 18K, 19K, 25K, 29K, 36K, 41K, 43K, 49K, 49K, 51K
# ruby-2.1.2: 21K, 33K, 42K, 49K, 55K, 55K, 55K, 62K, 71K, 71K
#
# data_append
# ruby-1.8.7: 3K, 3K, 3K, 3K, 3K, 3K, 3K, 3K, 3K, 3K
# ruby-1.9.3: 6K, 6K, 6K, 6K, 7K, 7K, 7K, 7K, 7K, 7K
# ruby-2.1.2: 18K, 25K, 31K, 36K, 38K, 42K, 45K, 48K, 49K, 50K
require 'rubygems' # for testing under <= 1.8.7
url = 'https://epub-samples.googlecode.com/files/mymedia_lite-20130621.epub'
file = './mymedia_lite-20130621.epub'
page = 'OEBPS/text/book_0002.xhtml' # file from zip above
page_size = 13_103 # size of page file above
unless File.exists?(file)
puts "Downloading test epub: #{url}"
`/usr/bin/env curl #{url} > #{file}`
end
class TestClass
def initialize(file_path, page_path, page_size)
@file_path = file_path
@page_path = page_path
@page_size = page_size
end
def data_times
('x' * @page_size)
end
def data_append
''.tap { |d| @page_size.times { d << 'x' } }
end
def read_zipruby
Zip::Archive.open(@file_path) {|zip|
zip.fopen(@page_path).read
}
end
def read_rubyzip
Zip::File.open(@file_path) do |zip|
zip.glob(@page_path).first.get_input_stream.read
end
end
def read_exec
`/usr/bin/env unzip -p #{@file_path} #{@page_path}`
end
end
method_list = %w[ read_zipruby read_rubyzip read_exec data_times data_append ]
method_name = ARGV[0]
raise(["provide method name: ", method_list.join(', ') ].join) unless
method_list.include?(method_name)
case method_name
when 'read_zipruby'
require 'zipruby' # 0.3.6
when 'read_rubyzip'
require 'zip' # rubyzip 1.1.6
end
memory_stats = []
1.upto(10_000) do |i|
print '.'
x = TestClass.new(file, page, page_size).send(method_name.to_sym)
raise "Size mismatch: #{x.to_s.bytesize} != #{page_size}" unless
x.to_s.bytesize == page_size
if i % 1_000 == 0
print "#{i} "
sleep(0.5) # Give time for GC to come in.
mem = (`/usr/bin/env ps -o rss -p #{$$}`.strip.split.last.to_i/1000).to_s + 'K'
puts mem
memory_stats << mem
end
end
puts "\n#{method_name}: #{memory_stats.join(', ')}"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment