Project

General

Profile

Feature #2065 ยป cache_benchmark.rb

bahuvrihi (Simon Chiang), 03/19/2010 05:37 AM

 
require 'benchmark'

# A basic version of a dsl that registers key-value pairs onto a Class. When
# looking up a key-value pair, Classes that use the dsl will check the
# registry of each ancestor in order, as if looking up a method.
#
# Call cache_ancestors! to cache the ancestry and speedup lookup.
module Dsl
def self.extended(base)
base.registry ||= {}
base.cache = nil
end
def inherited(base)
base.registry ||= {}
base.cache = nil
end
attr_accessor :registry
attr_accessor :cache
def set(key, value)
registry[key] = value
end
def value(key)
each_ancestor do |ancestor|
if ancestor.registry.has_key?(key)
return ancestor.registry[key]
end
end
end
def cache_ancestors!
@cache = ancestors
end
def each_ancestor
(cache || ancestors).each {|ancestor| yield(ancestor)}
end
end

# Now the benchmarks, first without caching (ie regenerate ancestors each
# time), then with caching to model performance with an each_ancestor method.
puts "Benchmark without cache"

class A
extend Dsl
set(:one, 1)
end

class B < A
set(:two, 2)
end

class C < B
set(:three, 3)
end

Benchmark.bm(20) do |x|
n = 100000
x.report "A.value(:one)" do
n.times { A.value(:one) }
end
x.report "B.value(:two)" do
n.times { B.value(:two) }
end
x.report "C.value(:three)" do
n.times { C.value(:three) }
end
end

puts
puts "Benchmark with cache"
A.cache_ancestors!
B.cache_ancestors!
C.cache_ancestors!

Benchmark.bm(20) do |x|
n = 100000
x.report "A.value(:one)" do
n.times { A.value(:one) }
end
x.report "B.value(:two)" do
n.times { B.value(:two) }
end
x.report "C.value(:three)" do
n.times { C.value(:three) }
end
x.report "Array.new" do
n.times { Array.new }
end
end

    (1-1/1)