Project

General

Profile

Feature #11688 ยป bm_dig.rb

nobu (Nobuyoshi Nakada), 11/16/2015 09:40 AM

 
require 'benchmark'
require 'ostruct'

opt = {
trace_instruction: false,
tailcall_optimization: true,
peephole_optimization: true,
}
RubyVM::InstructionSequence.compile(src = <<END, __FILE__, __FILE__, __LINE__, opt).eval
class Array
def dig_2(idx, *rest)
if rest.empty?
self[idx]
elsif !nil.equal?(v = self[idx])
v.dig_2(*rest)
end
end
end
class Hash
def dig_2(idx, *rest)
if rest.empty?
self[idx]
elsif !nil.equal?(v = self[idx])
v.dig_2(*rest)
end
end
end
class OpenStruct
def dig(name, *names)
name = name.to_sym
table = @table
if names.empty?
table[name]
elsif !nil.equal?(name = self[name])
name.dig(*names)
end
end
def dig_2(name, *names)
name = name.to_sym
table = @table
if names.empty?
table[name]
elsif !nil.equal?(name = self[name])
name.dig_2(*names)
end
end
end
END

a = []
100.times {a = [a]}
l = [:a]*100
o = a
h = a
mh = []
mo = []
l.reverse_each {|i|
h = {i => h}
o = OpenStruct.new(i => o)
mh = {i => [mh]}
mo = OpenStruct.new(i => [mo])
}
l2 = l + [0]*100
l3 = [:a, 0]*100

N = 20_000

Benchmark.bm(24) do |x|
x.report("Hash only(C)") {N.times {h.dig(*l)}}
x.report("Hash only(Ruby)") {N.times {h.dig_2(*l)}}
x.report("Hash+Array (C)") {N.times {h.dig(*l2)}}
x.report("Hash+Array (Ruby)") {N.times {h.dig_2(*l2)}}
x.report("OpenStruct (C)") {N.times {o.dig(*l)}}
x.report("OpenStruct (Ruby)") {N.times {o.dig_2(*l)}}
x.report("OpenStruct+Array (C)") {N.times {o.dig(*l2)}}
x.report("OpenStruct+Array (Ruby)") {N.times {o.dig_2(*l2)}}
x.report("Mix Hash (C)") {N.times {mh.dig(*l3)}}
x.report("Mix Hash (RUBY)") {N.times {mh.dig_2(*l3)}}
x.report("Mix OpenStruct (C)") {N.times {mo.dig(*l3)}}
x.report("Mix OpenStruct (Ruby)") {N.times {mo.dig_2(*l3)}}
end
    (1-1/1)