Skip to content

Instantly share code, notes, and snippets.

@fidelisrafael
Last active August 4, 2016 05:47
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fidelisrafael/d8509eea8ddac3e61c4ada2d706ee53b to your computer and use it in GitHub Desktop.
Save fidelisrafael/d8509eea8ddac3e61c4ada2d706ee53b to your computer and use it in GitHub Desktop.
Railtie register block benchmarks
require 'benchmark/ips'
module Cases
module Helpers
def clear!
@rake_tasks = nil
@generators = nil
end
end
class BlockRegisterInstanceEval
class << self
include Helpers
def rake_tasks(&blk)
register_block_for(:rake_tasks, &blk)
end
def generators(&blk)
register_block_for(:generators, &blk)
end
def register_block_for(type, &blk)
code = <<-EOF
@#{type} ||= []
@#{type} << blk if blk
@#{type}
EOF
instance_eval(code)
end
end
end
class BlockRegisterVarInit
class << self
include Helpers
def rake_tasks(&blk)
register_block_for(@rake_tasks ||= [], &blk)
end
def generators(&blk)
register_block_for(@generators ||= [], &blk)
end
def register_block_for(variable, &blk)
variable ||= []
variable << blk if blk
variable
end
end
end
class RailtieCurrentBlockRegister
class << self
include Helpers
def rake_tasks(&blk)
@rake_tasks ||= []
@rake_tasks << blk if blk
@rake_tasks
end
def generators(&blk)
@generators ||= []
@generators << blk if blk
@generators
end
end
end
class BlockRegisterSymbol
class << self
include Helpers
def rake_tasks(&blk)
register_block_for(:rake_tasks, &blk)
end
def generators(&blk)
register_block_for(:generators, &blk)
end
def register_block_for(type, &blk)
var_name = "@#{type}"
variable = instance_variable_get(var_name) || instance_variable_set(var_name, [])
variable << blk if blk
variable
end
end
end
end
def puts_message(message, width = 50, char = "=")
puts # new line
puts [char * width, message, char * width].join("\n")
puts # new line
end
def clear!
Cases::BlockRegisterInstanceEval.clear!
Cases::BlockRegisterVarInit.clear!
Cases::RailtieCurrentBlockRegister.clear!
Cases::BlockRegisterSymbol.clear!
end
def new_benchmark(message)
clear!
puts_message message
end
new_benchmark 'single `rake_task` method call inside loop'
Benchmark.ips do |x|
# slowest
x.report('instance_eval') do
Cases::BlockRegisterInstanceEval.rake_tasks { puts 'first rake task' }
end
# good
x.report('variable init') do
Cases::BlockRegisterVarInit.rake_tasks { puts 'first rake task' }
end
# good
x.report('variable get/set') do
Cases::BlockRegisterSymbol.rake_tasks { puts 'first rake task' }
end
# good
x.report('current railties') do
Cases::RailtieCurrentBlockRegister.rake_tasks { puts 'first rake task' }
end
x.compare!
end
new_benchmark "Single `generators` method call inside loop"
Benchmark.ips do |x|
# slowest
x.report('instance_eval') do
Cases::BlockRegisterInstanceEval.generators { puts 'first generator' }
end
# good
x.report('variable init') do
Cases::BlockRegisterVarInit.generators { puts 'first generator' }
end
# good
x.report('variable get/set') do
Cases::BlockRegisterSymbol.generators { puts 'first generator' }
end
# good
x.report('current railties') do
Cases::RailtieCurrentBlockRegister.generators { puts 'first generator' }
end
x.compare!
end
new_benchmark '4 methods calls inside each loop'
Benchmark.ips do |x|
# slowest
x.report('instance_eval') do
Cases::BlockRegisterInstanceEval.rake_tasks { puts 'first rake task' }
Cases::BlockRegisterInstanceEval.generators { puts 'Testing generator block' }
Cases::BlockRegisterInstanceEval.rake_tasks { puts 'second rake task' }
Cases::BlockRegisterInstanceEval.generators { puts 'Second generator block test' }
end
# good
x.report('variable init') do
Cases::BlockRegisterVarInit.rake_tasks { puts 'first rake task' }
Cases::BlockRegisterVarInit.generators { puts 'Testing generator block' }
Cases::BlockRegisterVarInit.rake_tasks { puts 'second rake task' }
Cases::BlockRegisterVarInit.generators { puts 'Second generator block test' }
end
# good
x.report('variable get/set') do
Cases::BlockRegisterSymbol.rake_tasks { puts 'first rake task' }
Cases::BlockRegisterSymbol.generators { puts 'Testing generator block' }
Cases::BlockRegisterSymbol.rake_tasks { puts 'second rake task' }
Cases::BlockRegisterSymbol.generators { puts 'Second generator block test' }
end
# good
x.report('current railties') do
Cases::RailtieCurrentBlockRegister.rake_tasks { puts 'first rake task' }
Cases::RailtieCurrentBlockRegister.generators { puts 'Testing generator block' }
Cases::RailtieCurrentBlockRegister.rake_tasks { puts 'second rake task' }
Cases::RailtieCurrentBlockRegister.generators { puts 'Second generator block test' }
end
x.compare!
end
=begin
==================================================
single `rake_task` method call inside loop
==================================================
Warming up --------------------------------------
instance_eval 4.036k i/100ms
variable init 39.834k i/100ms
variable get/set 31.997k i/100ms
current railties 35.253k i/100ms
Calculating -------------------------------------
instance_eval 50.476k (±32.1%) i/s - 185.656k in 5.792784s
variable init 977.498k (±56.9%) i/s - 1.315M in 5.415631s
variable get/set 651.734k (±48.1%) i/s - 1.056M in 5.033967s
current railties 1.417M (±37.0%) i/s - 1.128M in 7.740616s
Comparison:
current railties: 1416776.9 i/s
variable init: 977498.0 i/s - same-ish: difference falls within error
variable get/set: 651733.6 i/s - same-ish: difference falls within error
instance_eval: 50476.3 i/s - 28.07x slower
==================================================
Single `generators` method call inside loop
==================================================
Warming up --------------------------------------
instance_eval 3.460k i/100ms
variable init 59.450k i/100ms
variable get/set 39.731k i/100ms
current railties 50.625k i/100ms
Calculating -------------------------------------
instance_eval 56.878k (±24.7%) i/s - 214.520k in 5.362425s
variable init 1.114M (±53.8%) i/s - 1.784M in 5.180813s
variable get/set 735.448k (±38.6%) i/s - 1.391M in 5.983204s
current railties 1.108M (±60.7%) i/s - 1.063M in 5.020838s
Comparison:
variable init: 1114123.1 i/s
current railties: 1108297.5 i/s - same-ish: difference falls within error
variable get/set: 735447.9 i/s - same-ish: difference falls within error
instance_eval: 56878.4 i/s - 19.59x slower
==================================================
4 methods calls inside each loop
==================================================
Warming up --------------------------------------
instance_eval 1.159k i/100ms
variable init 25.411k i/100ms
variable get/set 17.967k i/100ms
current railties 19.728k i/100ms
Calculating -------------------------------------
instance_eval 14.180k (±29.9%) i/s - 53.314k in 5.469904s
variable init 377.365k (±53.4%) i/s - 736.919k in 6.285703s
variable get/set 222.860k (±41.0%) i/s - 521.043k in 5.979247s
current railties 504.417k (±42.5%) i/s - 493.200k in 5.210466s
Comparison:
current railties: 504417.5 i/s
variable init: 377364.7 i/s - same-ish: difference falls within error
variable get/set: 222860.0 i/s - same-ish: difference falls within error
instance_eval: 14180.2 i/s - 35.57x slower
=end
require 'benchmark'
module Cases
module Helpers
def clear!
@rake_tasks = nil
@generators = nil
end
end
class BlockRegisterInstanceEval
class << self
include Helpers
def rake_tasks(&blk)
register_block_for(:rake_tasks, &blk)
end
def generators(&blk)
register_block_for(:generators, &blk)
end
def register_block_for(type, &blk)
code = <<-EOF
@#{type} ||= []
@#{type} << blk if blk
@#{type}
EOF
instance_eval(code)
end
end
end
class BlockRegisterVarInit
class << self
include Helpers
def rake_tasks(&blk)
register_block_for(@rake_tasks, &blk)
end
def generators(&blk)
register_block_for(@generators, &blk)
end
def register_block_for(variable, &blk)
variable ||= []
variable << blk if blk
variable
end
end
end
class BlockRegisterSymbol
class << self
include Helpers
def rake_tasks(&blk)
register_block_for(:rake_tasks, &blk)
end
def generators(&blk)
register_block_for(:generators, &blk)
end
def register_block_for(type, &blk)
var_name = "@#{type}"
variable = instance_variable_get(var_name) || instance_variable_set(var_name, [])
variable << blk if blk
variable
end
end
end
class RailtieCurrentBlockRegister
class << self
include Helpers
def rake_tasks(&blk)
@rake_tasks ||= []
@rake_tasks << blk if blk
@rake_tasks
end
def generators(&blk)
@generators ||= []
@generators << blk if blk
@generators
end
end
end
end
def puts_message(message, width = 50, char = "=")
puts # new line
puts [char * width, message, char * width].join("\n")
puts # new line
end
def clear!
Cases::BlockRegisterInstanceEval.clear!
Cases::BlockRegisterVarInit.clear!
Cases::RailtieCurrentBlockRegister.clear!
Cases::BlockRegisterSymbol.clear!
end
def new_benchmark(message)
clear!
puts_message message
end
new_benchmark 'single `rake_task` method call inside loop'
Benchmark.bm(50) do |b|
# slowest
b.report('instance_eval') do
100_000.times do
Cases::BlockRegisterInstanceEval.rake_tasks { puts 'first rake task' }
end
end
# good
b.report('variable init') do
100_000.times do
Cases::BlockRegisterVarInit.rake_tasks { puts 'first rake task' }
end
end
b.report('instance variable get/set') do
100_000.times do
Cases::BlockRegisterSymbol.rake_tasks { puts 'first rake task' }
end
end
# good
b.report('current railties') do
100_000.times do
Cases::RailtieCurrentBlockRegister.rake_tasks { puts 'first rake task' }
end
end
end
new_benchmark "Single `generators` method call inside loop"
Benchmark.bm(50) do |b|
# slowest
b.report('instance_eval') do
100_000.times do
Cases::BlockRegisterInstanceEval.generators { puts 'first generator' }
end
end
# good
b.report('variable init') do
100_000.times do
Cases::BlockRegisterVarInit.generators { puts 'first generator' }
end
end
b.report('instance variable get/set') do
100_000.times do
Cases::BlockRegisterSymbol.generators { puts 'first generator' }
end
end
# good
b.report('current railties') do
100_000.times do
Cases::RailtieCurrentBlockRegister.generators { puts 'first generator' }
end
end
end
new_benchmark '4 methods calls inside each loop'
Benchmark.bm(50) do |b|
# slowest
b.report('instance_eval') do
100_000.times do
Cases::BlockRegisterInstanceEval.rake_tasks { puts 'first rake task' }
Cases::BlockRegisterInstanceEval.generators { puts 'Testing generator block' }
Cases::BlockRegisterInstanceEval.rake_tasks { puts 'second rake task' }
Cases::BlockRegisterInstanceEval.generators { puts 'Second generator block test' }
end
end
# good
b.report('variable init') do
100_000.times do
Cases::BlockRegisterVarInit.rake_tasks { puts 'first rake task' }
Cases::BlockRegisterVarInit.generators { puts 'Testing generator block' }
Cases::BlockRegisterVarInit.rake_tasks { puts 'second rake task' }
Cases::BlockRegisterVarInit.generators { puts 'Second generator block test' }
end
end
# good
b.report('instance variable get/set') do
100_000.times do
Cases::BlockRegisterSymbol.rake_tasks { puts 'first rake task' }
Cases::BlockRegisterSymbol.generators { puts 'Testing generator block' }
Cases::BlockRegisterSymbol.rake_tasks { puts 'second rake task' }
Cases::BlockRegisterSymbol.generators { puts 'Second generator block test' }
end
end
# good
b.report('current railties') do
100_000.times do
Cases::RailtieCurrentBlockRegister.rake_tasks { puts 'first rake task' }
Cases::RailtieCurrentBlockRegister.generators { puts 'Testing generator block' }
Cases::RailtieCurrentBlockRegister.rake_tasks { puts 'second rake task' }
Cases::RailtieCurrentBlockRegister.generators { puts 'Second generator block test' }
end
end
end
=begin
==================================================
single `rake_task` method call inside loop
==================================================
user system total real
instance_eval 2.350000 0.020000 2.370000 ( 2.366487)
variable init 0.180000 0.000000 0.180000 ( 0.176445)
instance variable get/set 0.160000 0.000000 0.160000 ( 0.162669)
current railties 0.250000 0.000000 0.250000 ( 0.252082)
==================================================
Single `generators` method call inside loop
==================================================
user system total real
instance_eval 2.260000 0.020000 2.280000 ( 2.273899)
variable init 0.120000 0.000000 0.120000 ( 0.115172)
instance variable get/set 0.160000 0.000000 0.160000 ( 0.161243)
current railties 0.160000 0.000000 0.160000 ( 0.160353)
==================================================
4 methods calls inside each loop
==================================================
user system total real
instance_eval 9.090000 0.000000 9.090000 ( 9.091285)
variable init 0.580000 0.000000 0.580000 ( 0.579077)
instance variable get/set 0.920000 0.000000 0.920000 ( 0.915160)
current railties 1.160000 0.020000 1.180000 ( 1.188045)
=end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment