Skip to content

Instantly share code, notes, and snippets.

@byroot
Last active September 5, 2021 12:52
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 byroot/cb3bcadcc3701c2518d002fb8d3a4e7a to your computer and use it in GitHub Desktop.
Save byroot/cb3bcadcc3701c2518d002fb8d3a4e7a to your computer and use it in GitHub Desktop.
Impact of stack size on exceptions performance
$ ruby -v
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin17]
$ ruby yield-vs-block.rb
Nested yield stack size: 402
Forward block stack size: 202
Warming up --------------------------------------
baseline 82.138k i/100ms
nested-yield 16.030k i/100ms
forward-block 28.945k i/100ms
Calculating -------------------------------------
baseline 816.998k (± 2.9%) i/s - 4.107M in 5.031495s
nested-yield 178.248k (± 4.4%) i/s - 897.680k in 5.046095s
forward-block 280.624k (± 4.5%) i/s - 1.418M in 5.064693s
Comparison:
baseline: 816998.1 i/s
forward-block: 280623.7 i/s - 2.91x (± 0.00) slower
nested-yield: 178247.6 i/s - 4.58x (± 0.00) slower
require 'benchmark/ips'
module Bench
extend self
DummyError = Class.new(StandardError)
STACK_SIZE = Integer(ENV.fetch("STACK_SIZE", 200))
def nested_yield_0
yield
end
def forward_block_0
yield
end
(1..STACK_SIZE).each do |i|
class_eval(<<~RUBY, __FILE__, __LINE__ + 1)
def nested_yield_#{i}
nested_yield_#{i - 1} { yield }
end
def forward_block_#{i}(&block)
forward_block_#{i - 1}(&block)
end
RUBY
end
alias_method :nested_yield, :"nested_yield_#{STACK_SIZE}"
alias_method :forward_block, :"forward_block_#{STACK_SIZE}"
end
puts "Nested yield stack size: #{Bench.nested_yield { caller.size }}"
puts "Forward block stack size: #{Bench.forward_block { caller.size }}"
Benchmark.ips do |x|
x.report('baseline') do |times|
i = 0
while i < times
begin
raise Bench::DummyError
rescue Bench::DummyError
end
i += 1
end
end
x.report('nested-yield') do |times|
Bench.nested_yield do
i = 0
while i < times
begin
raise Bench::DummyError
rescue Bench::DummyError
end
i += 1
end
end
end
x.report('forward-block') do |times|
Bench.forward_block do
i = 0
while i < times
begin
raise Bench::DummyError
rescue Bench::DummyError
end
i += 1
end
end
end
x.compare!
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment