Skip to content

Instantly share code, notes, and snippets.

@JangoSteve
Created April 26, 2010 19:29
Show Gist options
  • Save JangoSteve/379771 to your computer and use it in GitHub Desktop.
Save JangoSteve/379771 to your computer and use it in GitHub Desktop.
# Created by Steve Schwartz [1] (for Alfa Jango [2]) with the help of David Leal [3]
# [1] http://github.com/jangosteve
# [2] http://www.alfajango.com
# [3] http://github.com/david
# The latest version of this script may be found at http://gist.github.com/371710
require 'benchmark'
class OptionsHashBenchmarker
# assume an options hash of options => {:this => {:that => 'other'}}
# and we want to do some operation if options[:this][:that] is defined and true
VALID_OPTIONS = {:this => {:that => 'other'}}
OTHER_OPTIONS = {:nothing => 'stuff'}
def self.rescue_method(options={})
begin
if options[:this][:that]
#p "rescue_method doing stuff"
end
rescue
ensure
#p "rescue_method doing more stuff"
end
end
def self.chained_tries(options={})
if options.try(:[], :this).try(:[], :that)
#p "chained_tries doing stuff"
end
#p "chained_tries doing more stuff"
end
def self.chained_if(options={})
if options && options[:this] && options[:this][:that]
#p "chained_if doing stuff"
end
#p "chained_if doing more stuff"
end
def self.hash_extension(options={})
if options.deep_fetch(:this, :that)
#p "hash_extension doing stuff"
end
#p "hash_extension doing other stuff"
end
def self.nil_extension(options={})
if options[:this][:that]
#p "nil_extension doing stuff"
end
#p "nil_extension doing more stuff"
end
def self.test_normal
Hash.class_eval do
def deep_fetch(*keys)
keys.inject(self) { |h, k| if h then h[k] else return h end }
end
end
n=1000000
Benchmark.bm do |x|
x.report("rescue_method (valid):") { n.times do ; rescue_method(VALID_OPTIONS); end }
x.report("chained_tries (valid):") { n.times do ; chained_tries(VALID_OPTIONS); end }
x.report("chained_if (valid):") { n.times do ; chained_if(VALID_OPTIONS); end }
x.report("hash_extension (valid):") { n.times do ; hash_extension(VALID_OPTIONS); end }
x.report("rescue_method (other):") { n.times do ; rescue_method(OTHER_OPTIONS); end }
x.report("chained_tries (other):") { n.times do ; chained_tries(OTHER_OPTIONS); end }
x.report("chained_if (other):") { n.times do ; chained_if(OTHER_OPTIONS); end }
x.report("hash_extension (other):") { n.times do ; hash_extension(OTHER_OPTIONS); end }
x.report("rescue_method (none):") { n.times do ; rescue_method; end }
x.report("chained_tries (none):") { n.times do ; chained_tries; end }
x.report("chained_if (none):") { n.times do ; chained_if; end }
x.report("hash_extension (none):") { n.times do ; hash_extension; end }
end
end
# nil_extension must be put into its own method, so that NilClass doesn't get extended for the rescue_method (which would then never call the rescue block since it would no longer generate an exception)
def self.test_nil_extension
NilClass.class_eval do
def [](key)
nil
end
end
n=1000000
Benchmark.bm do |x|
x.report("nil_extension (valid):") { n.times do ; nil_extension(VALID_OPTIONS); end }
x.report("nil_extension (other):") { n.times do ; nil_extension(OTHER_OPTIONS); end }
x.report("nil_extension (none):") { n.times do ; nil_extension; end }
end
end
end
@JangoSteve
Copy link
Author

Run again on Ruby 1.8, this time with new Hash#deep_find extension:

  user     system      total        real

rescue_method (valid): 0.700000 0.010000 0.710000 ( 0.708726)
chained_tries (valid): 0.800000 0.000000 0.800000 ( 0.823636)
chained_if (valid): 0.800000 0.010000 0.810000 ( 0.844903)
nil_extension (valid): 0.600000 0.000000 0.600000 ( 0.611619)
hash_extension (valid): 3.060000 0.020000 3.080000 ( 3.153540)

rescue_method (other): 37.810000 1.420000 39.230000 ( 40.710294)
chained_tries (other): 1.230000 0.010000 1.240000 ( 1.268215)
chained_if (other): 0.650000 0.000000 0.650000 ( 0.680624)
nil_extension (other): 0.840000 0.000000 0.840000 ( 0.863451)
hash_extension (other): 3.500000 0.020000 3.520000 ( 3.548087)

rescue_method (none): 38.070000 1.410000 39.480000 ( 40.272977)
chained_tries (none): 2.080000 0.010000 2.090000 ( 2.120892)
chained_if (none): 1.410000 0.010000 1.420000 ( 1.417036)
nil_extension (none): 1.610000 0.010000 1.620000 ( 1.637559)
hash_extension (none): 4.310000 0.010000 4.320000 ( 4.503614)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment