Skip to content

Instantly share code, notes, and snippets.

@cupakromer cupakromer/README.md
Last active Aug 29, 2015

Embed
What would you like to do?

TL;DR

Both methods are nearly identical in perf. Differences are due more to underlying forwarded messages' implementation than how the message forwarding is defined.

Summary

Error rates between each type, for the most part, negate any real ranking. A real stat analysis would be necessary to make a real determination.

Grouped by Command style:

Run Command Yield Command Yield (Org) Command Call Command Call (Org)
1 224069.0 (±11.3%) i/s 227037.6 (±9.4%) i/s 205042.9 (±13.2%) i/s 212378.1 (±11.5%) i/s
2 196817.8 (±10.4%) i/s 195754.9 (±10.7%) i/s 189370.0 (±11.8%) i/s 191440.7 (±10.8%) i/s
3 184519.9 (±13.6%) i/s 177827.8 (±15.1%) i/s 177708.1 (±13.7%) i/s 175607.0 (±14.7%) i/s

Grouped by Query style:

Run Query Yield Query Yield (Org) Query Call Query Call (Org)
1 228332.1 (±8.9%) i/s 213187.1 (±14.8%) i/s 196810.4 (±15.8%) i/s 187438.8 (±15.8%) i/s
2 202684.5 (±15.5%) i/s 201411.5 (±15.9%) i/s 196702.8 (±16.4%) i/s 194909.3 (±16.3%) i/s
3 184557.5 (±14.1%) i/s 193942.4 (±12.8%) i/s 178738.8 (±15.1%) i/s 185981.8 (±10.9%) i/s

In rank order:

Run 1 Run 2 Run 3
  • Query Yield
  • Command Yield (Org)
  • Command Yield
  • Query Yield (Org)
  • Command Call (Org)
  • Command Call
  • Query Call
  • Query Call (Org)

Machine

  • MRI Ruby 2.1.3
  • Macbook Air 2012 (OS X 10.9.4, 1.8 GHz Intel Core i5, 8GB 1600 MHz DDR3)

Test Run #1

Calculating -------------------------------------
Command message with block to message using yield
                         13967 i/100ms
Command message with block to message using call
                         14445 i/100ms
(Org) Command message with block to message using yield
                         15055 i/100ms
(Org) Command message with block to message using call
                         13646 i/100ms
Query message with block to message using yield
                         15628 i/100ms
Query message with block to message using call
                         14149 i/100ms
(Org) Query message with block to message using yield
                         14159 i/100ms
(Org) Query message with block to message using call
                         14834 i/100ms
-------------------------------------------------
Command message with block to message using yield
                       224069.0 (±11.3%) i/s -    1117360 in   5.061352s
Command message with block to message using call
                       205042.9 (±13.2%) i/s -    1011150 in   5.038566s
(Org) Command message with block to message using yield
                       227037.6 (±9.4%) i/s -    1129125 in   5.028497s
(Org) Command message with block to message using call
                       212378.1 (±11.5%) i/s -    1050742 in   5.026626s
Query message with block to message using yield
                       228332.1 (±8.9%) i/s -    1140844 in   5.045268s
Query message with block to message using call
                       196810.4 (±15.8%) i/s -     976281 in   5.119127s
(Org) Query message with block to message using yield
                       213187.1 (±14.8%) i/s -    1047766 in   5.047181s
(Org) Query message with block to message using call
                       187438.8 (±15.8%) i/s -     919708 in   5.041849s

Test Run #2

Calculating -------------------------------------
Command message with block to message using yield
                         12414 i/100ms
Command message with block to message using call
                         13097 i/100ms
(Org) Command message with block to message using yield
                         14254 i/100ms
(Org) Command message with block to message using call
                         13655 i/100ms
Query message with block to message using yield
                         13783 i/100ms
Query message with block to message using call
                         12134 i/100ms
(Org) Query message with block to message using yield
                         14120 i/100ms
(Org) Query message with block to message using call
                         13832 i/100ms
-------------------------------------------------
Command message with block to message using yield
                       196817.8 (±10.4%) i/s -     980706 in   5.044359s
Command message with block to message using call
                       189370.0 (±11.8%) i/s -     942984 in   5.062401s
(Org) Command message with block to message using yield
                       195754.9 (±10.7%) i/s -     969272 in   5.019372s
(Org) Command message with block to message using call
                       191440.7 (±10.8%) i/s -     955850 in   5.063915s
Query message with block to message using yield
                       202684.5 (±15.5%) i/s -     992376 in   5.040518s
Query message with block to message using call
                       196702.8 (±16.4%) i/s -     958586 in   5.038450s
(Org) Query message with block to message using yield
                       201411.5 (±15.9%) i/s -     988400 in   5.061654s
(Org) Query message with block to message using call
                       194909.3 (±16.3%) i/s -     954408 in   5.055687s

Test Run #3

Calculating -------------------------------------
Command message with block to message using yield
                         13694 i/100ms
Command message with block to message using call
                         14203 i/100ms
(Org) Command message with block to message using yield
                         14299 i/100ms
(Org) Command message with block to message using call
                         13826 i/100ms
Query message with block to message using yield
                         14279 i/100ms
Query message with block to message using call
                         13383 i/100ms
(Org) Query message with block to message using yield
                         14594 i/100ms
(Org) Query message with block to message using call
                         14112 i/100ms
-------------------------------------------------
Command message with block to message using yield
                       184519.9 (±13.6%) i/s -     903804 in   5.014295s
Command message with block to message using call
                       177708.1 (±13.7%) i/s -     880586 in   5.067764s
(Org) Command message with block to message using yield
                       177827.8 (±15.1%) i/s -     872239 in   5.039058s
(Org) Command message with block to message using call
                       175607.0 (±14.7%) i/s -     857212 in   5.014550s
Query message with block to message using yield
                       184557.5 (±14.1%) i/s -     899577 in   5.006598s
Query message with block to message using call
                       178738.8 (±15.1%) i/s -     869895 in   5.015188s
(Org) Query message with block to message using yield
                       193942.4 (±12.8%) i/s -     948610 in   5.022701s
(Org) Query message with block to message using call
                       185981.8 (±10.9%) i/s -     917280 in   5.000594s
require "direction/version"
# Provide a feature like the Forwardable library,
# but set the return value to self.
# It provides a class level "command" method to do
# message forwarding.
#
# class SomeClass
# extend Direction
#
# command [:print_details, :setup_things] => :collaborator
# query [:name, :id] => :collaborator, :type => :@partner
# end
#
# This will define methods on instances that forward to the
# provided receiver while enforcing encapsulation of the
# relationship between objects.
module Direction
# Generates a string sufficient to forward messages to the accessor.
# Specify the return_value for the result of the forwarded message.
def self.message_handler(message, accessor, return_value)
%{
def #{message}(*args, &block)
#{accessor}.__send__(:#{message}, *args, &block)
#{return_value}
end
}
# %{
# def #{message}(*args)
# if block_given?
# #{accessor}.__send__(:#{message}, *args) { |*block_args| yield(*block_args) }
# else
# #{accessor}.__send__(:#{message}, *args)
# end
# #{return_value}
# end
# }
end
# Loops over a hash of options and defines methods to the apply_to module/class provided.
# Specify the return_value for the result of all forwarded messages.
def self.setup_forwarding(options, apply_to:, return_value: '')
method_defs = []
options.each_pair do |key, value|
Array(key).map do |command_name|
method_defs.unshift Direction.message_handler(command_name, value, return_value)
end
end
apply_to.class_eval method_defs.join(' '), __FILE__, __LINE__
end
# Forward messages and return self, protecting the encapsulation of the object
def command(options)
Direction.setup_forwarding(options, apply_to: self, return_value: 'self')
end
# Forward messages and return the result of the forwarded message
def query(options)
Direction.setup_forwarding(options, apply_to: self)
end
end
require "direction/version"
# Provide a feature like the Forwardable library,
# but set the return value to self.
# It provides a class level "command" method to do
# message forwarding.
#
# class SomeClass
# extend Direction
#
# command [:print_details, :setup_things] => :collaborator
# query [:name, :id] => :collaborator, :type => :@partner
# end
#
# This will define methods on instances that forward to the
# provided receiver while enforcing encapsulation of the
# relationship between objects.
module DirectionOrg
# Generates a string sufficient to forward messages to the accessor.
# Specify the return_value for the result of the forwarded message.
def self.message_handler(message, accessor, return_value)
%{
def #{message}(*args, &block)
#{accessor}.__send__(:#{message}, *args, &block)
#{return_value}
end
}
end
# Loops over a hash of options and defines methods to the apply_to module/class provided.
# Specify the return_value for the result of all forwarded messages.
def self.setup_forwarding(options, apply_to:, return_value: '')
method_defs = []
options.each_pair do |key, value|
Array(key).map do |command_name|
method_defs.unshift Direction.message_handler(command_name, value, return_value)
end
end
apply_to.class_eval method_defs.join(' '), __FILE__, __LINE__
end
# Forward messages and return self, protecting the encapsulation of the object
def command(options)
Direction.setup_forwarding(options, apply_to: self, return_value: 'self')
end
# Forward messages and return the result of the forwarded message
def query(options)
Direction.setup_forwarding(options, apply_to: self)
end
end
require 'direction'
require 'direction_org'
require 'benchmark/ips'
class PersonOrg
extend DirectionOrg
command [:make_me_a_sandwich, :cook, :blocky, :blocky_call] => :@friend
query [:activities, :go, :say_what, :say_what_call] => :friend
attr_accessor :friend
end
class Person
extend Direction
command [:make_me_a_sandwich, :cook, :blocky, :blocky_call] => :@friend
query [:activities, :go, :say_what, :say_what_call] => :friend
attr_accessor :friend
end
class Friend
def make_me_a_sandwich
end
def cook(what)
end
def activities
'running, biking, hiking'
end
def go(do_what)
end
def blocky(text)
yield(self)
end
def blocky_call(text, &block)
block.call(self)
end
def say_what(text)
yield(self)
end
def say_what_call(text, &block)
block.call(self)
end
end
person = Person.new
person.friend = Friend.new
person_org = PersonOrg.new
person_org.friend = Friend.new
Benchmark.ips do |r|
r.report('Command message with block to message using yield') do
person.blocky('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('Command message with block to message using call') do
person.blocky_call('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('(Org) Command message with block to message using yield') do
person_org.blocky('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('(Org) Command message with block to message using call') do
person_org.blocky_call('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('Query message with block to message using yield') do
person.say_what('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('Query message with block to message using call') do
person.say_what_call('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('(Org) Query message with block to message using yield') do
person_org.say_what('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
r.report('(Org) Query message with block to message using call') do
person_org.say_what_call('yay!') do |friend|
"Arguments forwarded to #{friend}"
end
end
end
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.