Created
June 15, 2014 21:21
-
-
Save matsumonkie/81aa64724424652b20a8 to your computer and use it in GitHub Desktop.
dci benchmarks
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'benchmark' | |
require 'delegate' | |
#--------------------------------------------------------------- | |
# ruby normal implementation | |
#--------------------------------------------------------------- | |
module Mover | |
def accelerate(speed:) | |
@speed += speed | |
end | |
end | |
class Car | |
include Mover | |
attr_reader :speed, :speed_limit | |
def initialize(speed: 0, speed_limit:) | |
@speed = speed | |
@speed_limit = speed_limit | |
end | |
end | |
def include_module | |
car = Car.new(speed: 0, speed_limit: 100) | |
car.accelerate(speed: 10) | |
car.accelerate(speed: 50) | |
car.accelerate(speed: 50) | |
end | |
#--------------------------------------------------------------- | |
# using a decorator | |
#--------------------------------------------------------------- | |
class Car2 | |
attr_accessor :speed, :speed_limit | |
def initialize(speed: 0, speed_limit:) | |
@speed = speed | |
@speed_limit = speed_limit | |
end | |
end | |
class Mover2 < SimpleDelegator | |
def initialize(car:) | |
super(car: car) | |
end | |
def accelerate(speed:) | |
self[:car].speed += speed | |
end | |
end | |
def decorator | |
car2 = Car2.new(speed: 0, speed_limit: 100) | |
mover2 = Mover2.new(car: car2) | |
mover2.accelerate(speed: 10) | |
mover2.accelerate(speed: 50) | |
mover2.accelerate(speed: 50) | |
end | |
#--------------------------------------------------------------- | |
# extending a module dynamically | |
#--------------------------------------------------------------- | |
class Car3 | |
attr_reader :speed, :speed_limit | |
def initialize(speed: 0, speed_limit:) | |
@speed = speed | |
@speed_limit = speed_limit | |
end | |
end | |
module Mover3 | |
def accelerate(speed:) | |
@speed += speed | |
end | |
end | |
class MoveContext | |
def self.call(movable:, speed:) | |
self.new(movable).run(speed) | |
end | |
def initialize(movable) | |
@movable = movable | |
@movable.extend(Mover) | |
end | |
def run(speed) | |
#puts "moving at #{@movable.speed} km/h, trying to accelerate" | |
if (@movable.speed + speed < @movable.speed_limit) | |
@movable.accelerate(speed: speed) | |
#puts "now moving at #{@movable.speed} km/h" | |
else | |
#puts "cannot accelerate anymore" | |
end | |
end | |
end | |
def dci_with_extend | |
car = Car3.new(speed: 0, speed_limit: 100) | |
MoveContext::call(movable: car, speed: 10) | |
MoveContext::call(movable: car, speed: 50) | |
MoveContext::call(movable: car, speed: 50) | |
end | |
#--------------------------------------------------------------- | |
# | |
#--------------------------------------------------------------- | |
module Role | |
attr_accessor :role | |
def method_missing(method_name, *args, &block) | |
if role && role.public_method_defined?(method_name) | |
role.instance_method(method_name).bind(self).call(*args, &block) | |
else | |
super | |
end | |
end | |
def respond_to_missing?(method_name, include_all=false) | |
if role && role.public_method_defined?(method_name) | |
true | |
else | |
super | |
end | |
end | |
def play_role(role) | |
self.role = role | |
yield(self) | |
ensure | |
self.role = nil | |
end | |
end | |
class Car4 | |
include Role | |
attr_reader :speed, :speed_limit | |
def initialize(speed: 0, speed_limit:) | |
@speed = speed | |
@speed_limit = speed_limit | |
end | |
end | |
module Mover4 | |
def accelerate(speed:) | |
@speed += speed | |
end | |
end | |
def dci_with_binding | |
car4 = Car4.new(speed: 0, speed_limit: 100) | |
car4.play_role(Mover4) do |c| | |
c.accelerate(speed: 10) | |
c.accelerate(speed: 50) | |
c.accelerate(speed: 50) | |
end | |
end | |
Benchmark.bm do |x| | |
n = 100_000 | |
padding = 16 | |
x.report("%#{padding}s" % 'include_module') { | |
n.times { include_module() } | |
} | |
x.report("%#{padding}s" % 'decorator') { | |
n.times { decorator() } | |
} | |
x.report("%#{padding}s" % 'dci_with_extend') { | |
n.times { dci_with_extend() } | |
} | |
x.report("%#{padding}s" % 'dci_with_binding') { | |
n.times { dci_with_binding() } | |
} | |
end | |
=begin | |
user system total real | |
include_module 0.460000 0.010000 0.470000 ( 0.463059) | |
decorator 0.760000 0.000000 0.760000 ( 0.767154) | |
dci_with_extend 1.130000 0.000000 1.130000 ( 1.135473) | |
dci_with_binding 1.000000 0.000000 1.000000 ( 0.998439) | |
=end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment