On a lark, I did this, and was shocked at the result. Why the massive
difference in performance between “begin; end” within a block, and “{ }”
within a block?
I may do some more tinkering with this later on.
require ‘benchmark’
N = 10_000_000
Benchmark.bmbm do |b|
b.report ‘begin’ do
N.times { begin; rescue; end }
end
b.report ‘begin no rescue’ do
N.times { begin; end }
end
b.report ‘no begin nested’ do
N.times { { } }
end
b.report ‘plain’ do
N.times { }
end
end
Rehearsal ---------------------------------------------------
begin 3.547000 0.000000 3.547000 ( 3.656000)
begin no rescue 2.797000 0.000000 2.797000 ( 2.860000)
no begin nested 38.062000 0.453000 38.515000 ( 40.593000)
plain 1.735000 0.000000 1.735000 ( 1.782000)
----------------------------------------- total: 46.594000sec
user system total real
begin 3.516000 0.000000 3.516000 ( 3.594000)
begin no rescue 2.750000 0.000000 2.750000 ( 2.828000)
no begin nested 36.422000 0.297000 36.719000 ( 38.797000)
plain 1.750000 0.000000 1.750000 ( 1.781000)
Pat: I think it already does and there’s still a performance hit.
Though Eric’s machine chugs a little more than mine, I’d be interested
to see what his ratios are with this added benchmark:
require ‘benchmark’
N = 10_000_000
Benchmark.bmbm do |b|
b.report ‘begin’ do
N.times { begin; rescue; end }
end
b.report ‘begin no rescue’ do
N.times { begin; end }
end
b.report ‘no begin’ do
N.times { }
end
end
G:\Documents and Settings\Dan Nugent\Desktop>ruby -v rescue.rb
ruby 1.8.4 (2005-12-24) [i386-mswin32]
Rehearsal ---------------------------------------------------
begin 3.703000 0.000000 3.703000 ( 3.844000)
begin no rescue 3.125000 0.000000 3.125000 ( 3.281000)
no begin 2.078000 0.000000 2.078000 ( 2.172000)
------------------------------------------ total: 8.906000sec
user system total real
begin 4.703000 0.000000 4.703000 ( 4.906000)
begin no rescue 3.203000 0.000000 3.203000 ( 3.312000)
no begin 2.047000 0.000000 2.047000 ( 2.141000)
b.report ‘begin no rescue’ do
N.times { begin; end }
end
b.report ‘no begin’ do
N.times { }
end
end
On my machine, WinXP Home SP2, 512mb RAM, Athlon 1900 (or so). Both
benchmarks run within irb.
Using Eric’s original code:
Rehearsal --------------------------------------------
begin 3.578000 0.000000 3.578000 ( 3.625000)
no begin 1.782000 0.000000 1.782000 ( 1.828000)
----------------------------------- total: 5.360000sec
user system total real
begin 3.547000 0.000000 3.547000 ( 3.625000)
no begin 1.796000 0.000000 1.796000 ( 1.812000)
100% increase between the two. Not as much as Eric’s, but still
significant I would think.
Using Daniel’s code:
Rehearsal ---------------------------------------------------
begin 3.546000 0.000000 3.546000 ( 3.625000)
begin no rescue 2.829000 0.000000 2.829000 ( 2.875000)
no begin 1.781000 0.000000 1.781000 ( 1.828000)
------------------------------------------ total: 8.156000sec
user system total real
begin 3.547000 0.000000 3.547000 ( 3.609000)
begin no rescue 2.812000 0.000000 2.812000 ( 2.891000)
no begin 1.735000 0.000000 1.735000 ( 1.797000)
Interesting middle ground there. So begin/end blocks have their own
overhead, above and beyond the exception handlers.
Note that I am not a benchmarking expert, and in fact am merely guessing
at the relative importance of the numbers, assuming the “real” values
are the important ones. I probably should read more about this module.
DÅ?a Streda 15 Február 2006 20:03 Dave C. napÃsal:
On a lark, I did this, and was shocked at the result. Why the massive
difference in performance between “begin; end” within a block, and “{ }”
within a block?
Because it’s a literal hash constructor, not a nested block?
On a slightly related note, the literal hash constructor is apparently
faster
than Hash.new. Good to know.