-
-
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 |
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)
Generates the following results running Ruby 1.8:
rescue_method (valid): 0.690000 0.010000 0.700000 ( 0.706048)
chained_tries (valid): 0.810000 0.010000 0.820000 ( 0.821056)
chained_if (valid): 0.790000 0.000000 0.790000 ( 0.803357)
nil_extension (valid): 0.610000 0.000000 0.610000 ( 0.624397)
rescue_method (other): 37.190000 1.410000 38.600000 ( 39.176910)
chained_tries (other): 1.220000 0.010000 1.230000 ( 1.232347)
chained_if (other): 0.640000 0.000000 0.640000 ( 0.649805)
nil_extension (other): 0.850000 0.010000 0.860000 ( 0.860668)
rescue_method (none): 37.700000 1.400000 39.100000 ( 39.871890)
chained_tries (none): 2.010000 0.010000 2.020000 ( 2.048758)
chained_if (none): 1.490000 0.010000 1.500000 ( 1.504774)
nil_extension (none): 1.580000 0.000000 1.580000 ( 1.611356)