Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Show the effects of method cache damage from runtime extend, as it relates to extend vs. delegate for DCI.
require 'benchmark'
number_of_rails_methods = 300
@rails = Class.new do
number_of_rails_methods.times do |i|
class_eval <<-RUBY
def call#{"%02d" % i} # def call01
end # end
RUBY
end
end.new
many_calls = Array.new(number_of_rails_methods) do |i|
"@rails.call#{'%02d' % i}"
end.join("\n")
eval <<-RUBY
def rails_does_other_stuff
#{many_calls}
end
RUBY
Person = Struct.new(:first_name, :last_name)
class DelegateDecorator
def initialize(target)
@target = target
end
def method_missing(n, *a, &b)
@target.__send__(n, *a, &b)
end
def full_name
"#{first_name} #{last_name}"
end
end
module DCIDecorator
def self.new(object)
object.extend(self)
object
end
def full_name
"#{first_name} #{last_name}"
end
end
many = 100000
puts "# #{many} iterations"
puts "# #{number_of_rails_methods} non-decorated calls"
Benchmark.bmbm(20) do |r|
r.report("plain dispatch") do
many.times do
person = Person.new("joe", "smith")
rails_does_other_stuff
end
end
r.report("some delegator") do
many.times do
person = Person.new("joe", "smith")
decorated = DelegateDecorator.new(person)
decorated.first_name
decorated.full_name
rails_does_other_stuff
end
end
r.report("some dci decorator") do
many.times do
person = Person.new("joe", "smith")
decorated = DCIDecorator.new(person)
decorated.first_name
decorated.full_name
rails_does_other_stuff
end
end
end
~ % ruby bm_dci_pounding.rb
# 100000 iterations
# 100 non-decorated calls
Rehearsal --------------------------------------------------------
plain dispatch 0.690000 0.000000 0.690000 ( 0.688859)
some delegator 0.840000 0.010000 0.850000 ( 0.848078)
some dci decorator 1.380000 0.000000 1.380000 ( 1.379049)
----------------------------------------------- total: 2.920000sec
user system total real
plain dispatch 0.700000 0.000000 0.700000 ( 0.692977)
some delegator 0.850000 0.000000 0.850000 ( 0.853181)
some dci decorator 1.420000 0.000000 1.420000 ( 1.414180)
~ % ruby bm_dci_pounding.rb
# 100000 iterations
# 200 non-decorated calls
Rehearsal --------------------------------------------------------
plain dispatch 1.310000 0.010000 1.320000 ( 1.315360)
some delegator 1.480000 0.000000 1.480000 ( 1.485176)
some dci decorator 2.490000 0.010000 2.500000 ( 2.493052)
----------------------------------------------- total: 5.300000sec
user system total real
plain dispatch 1.320000 0.000000 1.320000 ( 1.324366)
some delegator 1.490000 0.000000 1.490000 ( 1.491190)
some dci decorator 2.510000 0.000000 2.510000 ( 2.509399)
~ % ruby bm_dci_pounding.rb
# 100000 iterations
# 300 non-decorated calls
Rehearsal --------------------------------------------------------
plain dispatch 2.090000 0.010000 2.100000 ( 2.099575)
some delegator 2.280000 0.010000 2.290000 ( 2.283076)
some dci decorator 3.920000 0.010000 3.930000 ( 3.925663)
----------------------------------------------- total: 8.320000sec
user system total real
plain dispatch 2.080000 0.000000 2.080000 ( 2.085480)
some delegator 2.300000 0.000000 2.300000 ( 2.299252)
some dci decorator 3.950000 0.000000 3.950000 ( 3.944498)
~ % ruby bm_dci_pounding.rb
# 100000 iterations
# 1000 non-decorated calls
Rehearsal --------------------------------------------------------
plain dispatch 7.190000 0.020000 7.210000 ( 7.212247)
some delegator 7.320000 0.010000 7.330000 ( 7.325742)
some dci decorator 12.940000 0.000000 12.940000 ( 12.940868)
---------------------------------------------- total: 27.480000sec
user system total real
plain dispatch 7.250000 0.000000 7.250000 ( 7.264858)
some delegator 7.450000 0.010000 7.460000 ( 7.445777)
some dci decorator 13.060000 0.010000 13.070000 ( 13.070932)
@rsanheim

This comment has been minimized.

Copy link

rsanheim commented Sep 22, 2016

What version of ruby did you run against?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.