Rescuing blocks?

Hey guys,

I was working on a DSL for some asynchronous programming stuff and I
realized it'd be really nice if a block could rescue an exception.

So I went into IRB to see if it works and got a parse error. I
suppose you need a begin... end block or a proper method to have a
rescue block right now.

I was wondering if there's any reason why this is so? It'd seem
pretty natural to me that a block could have rescue/else/ensure
conditions since a method body can have them.

Has this been discussed elsewhere?

Thanks,

···

--
-Dan Nugent

Dňa Nedeľa 12 Február 2006 19:26 Daniel Nugent napísal:

Hey guys,

I was working on a DSL for some asynchronous programming stuff and I
realized it'd be really nice if a block could rescue an exception.

So I went into IRB to see if it works and got a parse error. I
suppose you need a begin... end block or a proper method to have a
rescue block right now.

I was wondering if there's any reason why this is so? It'd seem
pretty natural to me that a block could have rescue/else/ensure
conditions since a method body can have them.

Has this been discussed elsewhere?

Thanks,

--
-Dan Nugent

I'm afraid I don't quite catch your drift. What do you mean by a block not
rescuing an exception? Some example code wouldn't hurt.

David Vallner

Whoops, shoulda thought of that, a-doy.

Okay, it's pretty simple, here's what I'd like to do (you can
extrapolate the rest of the syntax from the simple example):

foo = [1, 2, 3]

foo.each do |o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
  puts e.to_s
end

And so on and so forth. It seems pretty natural to me.... I don't
think it breaks anything (least not off the top of my head)...

···

On 2/12/06, David Vallner <david@vallner.net> wrote:

Dňa Nedeľa 12 Február 2006 19:26 Daniel Nugent napísal:
> Hey guys,
>
> I was working on a DSL for some asynchronous programming stuff and I
> realized it'd be really nice if a block could rescue an exception.
>
> So I went into IRB to see if it works and got a parse error. I
> suppose you need a begin... end block or a proper method to have a
> rescue block right now.
>
> I was wondering if there's any reason why this is so? It'd seem
> pretty natural to me that a block could have rescue/else/ensure
> conditions since a method body can have them.
>
> Has this been discussed elsewhere?
>
> Thanks,
>
> --
> -Dan Nugent

I'm afraid I don't quite catch your drift. What do you mean by a block not
rescuing an exception? Some example code wouldn't hurt.

David Vallner

--
-Dan Nugent

this works,

foo = [1, 2, 3]

foo.each do |o|
  begin
    raise "Oh noes, it's number 2!" if o == 2
  rescue Exception => e
    puts e.to_s
  end
end

Daniel Nugent wrote:

···

Whoops, shoulda thought of that, a-doy.

Okay, it's pretty simple, here's what I'd like to do (you can
extrapolate the rest of the syntax from the simple example):

foo = [1, 2, 3]

foo.each do |o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
  puts e.to_s
end

And so on and so forth. It seems pretty natural to me.... I don't
think it breaks anything (least not off the top of my head)...

On 2/12/06, David Vallner <david@vallner.net> wrote:

Dňa Nedeľa 12 Február 2006 19:26 Daniel Nugent napísal:

Hey guys,

I was working on a DSL for some asynchronous programming stuff and I
realized it'd be really nice if a block could rescue an exception.

So I went into IRB to see if it works and got a parse error. I
suppose you need a begin... end block or a proper method to have a
rescue block right now.

I was wondering if there's any reason why this is so? It'd seem
pretty natural to me that a block could have rescue/else/ensure
conditions since a method body can have them.

Has this been discussed elsewhere?

Thanks,

--
-Dan Nugent

I'm afraid I don't quite catch your drift. What do you mean by a block not
rescuing an exception? Some example code wouldn't hurt.

David Vallner

--
-Dan Nugent

You're going to get a performance hit setting up an exception trap this way.

···

On Feb 12, 2006, at 10:55 AM, Daniel Nugent wrote:

Whoops, shoulda thought of that, a-doy.

Okay, it's pretty simple, here's what I'd like to do (you can
extrapolate the rest of the syntax from the simple example):

foo = [1, 2, 3]

foo.each do |o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
  puts e.to_s
end

And so on and so forth. It seems pretty natural to me.... I don't
think it breaks anything (least not off the top of my head)...

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

Sure it works, but Daniel wants to reduce the syntax a bit AND exit
the loop if an exception is raised without having to specify that. I
like his suggestion.

···

On 2/12/06, Lou Vanek <vanek@acd.net> wrote:

this works,

foo = [1, 2, 3]

foo.each do |o|
        begin
          raise "Oh noes, it's number 2!" if o == 2
        rescue Exception => e
          puts e.to_s
        end
end

--
R. Mark Volkmann
Partner, Object Computing, Inc.

Eric Hodel wrote:

foo = [1, 2, 3]

foo.each do |o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
  puts e.to_s
end

And so on and so forth. It seems pretty natural to me.... I don't
think it breaks anything (least not off the top of my head)...

You're going to get a performance hit setting up an exception trap this way.

Time for some down-South edumucation. What kind of performance hit are we talking about here? And why the hit at all?

(I seem to recall reading somewhere once upon a time about memory stack stuff, but I'm not an old-school C-programmer so I never had to deal with it --- unfortunately for me...)

-dave

Dňa Nedeľa 12 Február 2006 20:39 Mark Volkmann napísal:

···

On 2/12/06, Lou Vanek <vanek@acd.net> wrote:
> this works,
>
> foo = [1, 2, 3]
>
> foo.each do |o|
> begin
> raise "Oh noes, it's number 2!" if o == 2
> rescue Exception => e
> puts e.to_s
> end
> end

Sure it works, but Daniel wants to reduce the syntax a bit AND exit
the loop if an exception is raised without having to specify that. I
like his suggestion.

--
R. Mark Volkmann
Partner, Object Computing, Inc.

It would cause a little inconsistency with the curly brace form of blocks.
Either the rescue clause would have to work only for the do / end form, or
we'd be mixing braces and keywords in a single construct, which I couldn't
bear to look at.

David Vallner

Dave Cantrell wrote:

Eric Hodel wrote:

You're going to get a performance hit setting up an exception trap this way.

Time for some down-South edumucation. What kind of performance hit are we talking about here? And why the hit at all?

(I seem to recall reading somewhere once upon a time about memory stack stuff, but I'm not an old-school C-programmer so I never had to deal with it --- unfortunately for me...)

Well, my knowledge is limited. Someone else can answer better.

But look at it from a common-sense standpoint. Exceptions aren't
magic. Everything Ruby does can be done in assembly language, it's
just more verbose.

I would think that exceptions, at the lowest level, work something
like:

    if something_happened_here
       goto the_place_where_exceptions_are_caught

So at the very least, catching exceptions means that you're doing
some sort of comparison or conditional branch. And this is code
that doesn't have to be run/generated *unless* you are catching
exceptions.

Just my naive take.

Hal

Is

foo.each {|o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
    puts e.to_s
}

really that hideous?

···

On 2/12/06, David Vallner <david@vallner.net> wrote:

Dňa Nedeľa 12 Február 2006 20:39 Mark Volkmann napísal:
> On 2/12/06, Lou Vanek <vanek@acd.net> wrote:
> > this works,
> >
> > foo = [1, 2, 3]
> >
> > foo.each do |o|
> > begin
> > raise "Oh noes, it's number 2!" if o == 2
> > rescue Exception => e
> > puts e.to_s
> > end
> > end
>
> Sure it works, but Daniel wants to reduce the syntax a bit AND exit
> the loop if an exception is raised without having to specify that. I
> like his suggestion.
>
> --
> R. Mark Volkmann
> Partner, Object Computing, Inc.

It would cause a little inconsistency with the curly brace form of blocks.
Either the rescue clause would have to work only for the do / end form, or
we'd be mixing braces and keywords in a single construct, which I couldn't
bear to look at.

David Vallner

--
-Dan Nugent

Hal Fulton wrote:

Dave Cantrell wrote:

Eric Hodel wrote:

You're going to get a performance hit setting up an exception trap this way.

Time for some down-South edumucation. What kind of performance hit are we talking about here? And why the hit at all?

(I seem to recall reading somewhere once upon a time about memory stack stuff, but I'm not an old-school C-programmer so I never had to deal with it --- unfortunately for me...)

Well, my knowledge is limited. Someone else can answer better.

But look at it from a common-sense standpoint. Exceptions aren't
magic. Everything Ruby does can be done in assembly language, it's
just more verbose.

I would think that exceptions, at the lowest level, work something
like:

   if something_happened_here
      goto the_place_where_exceptions_are_caught

So at the very least, catching exceptions means that you're doing
some sort of comparison or conditional branch. And this is code
that doesn't have to be run/generated *unless* you are catching
exceptions.

Just my naive take.

Hal

That's kind of along the lines of what I was thinking, just better said. But this makes me wonder:

(a) Worrying about the performance hit from comparison/conditional branching leads to the question "is all branching in blocks bad?" Obviously not.

(b) Couldn't you say that *any* conditional could be jumping out to another section of code? i.e. not just exception handlers?

   if this_is_true
      goto where_we_do_stuff_when_this_is_true

Hmm. This is something I've read, and it's in my brain somewhere, but I don't know it well enough to grok it yet.

Especially at midnight... :frowning:

But your explanation gives me a better idea of what is happening, even with my questions.

Thanks!
-dave

Yes. You get a setup/teardown of an exception handler for every block. Right now class module and def have an implicit exception handler built in. Adding a begin; rescue; end explicitly to blocks gives you a very hefty penalty. That's no guarantee of similarly bad performance with an implicit exception handler, but it still won't be free.

I've very rarely found myself placing an exception handler directly inside a block so I don't think it would be worth it.

$ cat rescue.rb
require 'benchmark'

N = 10_000_000

Benchmark.bmbm do |b|
   b.report 'begin' do
     N.times { begin; rescue; end }
   end

   b.report 'no begin' do
     N.times { }
   end
end

$ ruby -v rescue.rb
ruby 1.8.4 (2005-12-24) [powerpc-darwin8.4.0]
Rehearsal --------------------------------------------
begin 6.330000 0.060000 6.390000 ( 8.303914)
no begin 2.580000 0.010000 2.590000 ( 3.178967)
----------------------------------- total: 8.980000sec

                user system total real
begin 6.320000 0.060000 6.380000 ( 8.597418)
no begin 2.570000 0.020000 2.590000 ( 3.526030)

···

On Feb 14, 2006, at 9:50 PM, Hal Fulton wrote:

Dave Cantrell wrote:

Eric Hodel wrote:

You're going to get a performance hit setting up an exception trap this way.

Time for some down-South edumucation. What kind of performance hit are we talking about here? And why the hit at all?
(I seem to recall reading somewhere once upon a time about memory stack stuff, but I'm not an old-school C-programmer so I never had to deal with it --- unfortunately for me...)

Well, my knowledge is limited. Someone else can answer better.

But look at it from a common-sense standpoint. Exceptions aren't
magic. Everything Ruby does can be done in assembly language, it's
just more verbose.

I would think that exceptions, at the lowest level, work something
like:

   if something_happened_here
      goto the_place_where_exceptions_are_caught

So at the very least, catching exceptions means that you're doing
some sort of comparison or conditional branch. And this is code
that doesn't have to be run/generated *unless* you are catching
exceptions.

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

How would you parse the difference whether the raise applies to the whole
block, or just the previous statement?

David Vallner

Dňa Nedeľa 12 Február 2006 21:43 Daniel Nugent napísal:

···

Is

foo.each {|o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
    puts e.to_s
}

really that hideous?

On 2/12/06, David Vallner <david@vallner.net> wrote:
> Dňa Nedeľa 12 Február 2006 20:39 Mark Volkmann napísal:
> > On 2/12/06, Lou Vanek <vanek@acd.net> wrote:
> > > this works,
> > >
> > > foo = [1, 2, 3]
> > >
> > > foo.each do |o|
> > > begin
> > > raise "Oh noes, it's number 2!" if o == 2
> > > rescue Exception => e
> > > puts e.to_s
> > > end
> > > end
> >
> > Sure it works, but Daniel wants to reduce the syntax a bit AND exit
> > the loop if an exception is raised without having to specify that. I
> > like his suggestion.
> >
> > --
> > R. Mark Volkmann
> > Partner, Object Computing, Inc.
>
> It would cause a little inconsistency with the curly brace form of
> blocks. Either the rescue clause would have to work only for the do / end
> form, or we'd be mixing braces and keywords in a single construct, which
> I couldn't bear to look at.
>
> David Vallner

--
-Dan Nugent

Dave Cantrell wrote:

Hal Fulton wrote:

Dave Cantrell wrote:

Eric Hodel wrote:

You're going to get a performance hit setting up an exception trap this way.

Time for some down-South edumucation. What kind of performance hit are we talking about here? And why the hit at all?

(I seem to recall reading somewhere once upon a time about memory stack stuff, but I'm not an old-school C-programmer so I never had to deal with it --- unfortunately for me...)

Well, my knowledge is limited. Someone else can answer better.

But look at it from a common-sense standpoint. Exceptions aren't
magic. Everything Ruby does can be done in assembly language, it's
just more verbose.

I would think that exceptions, at the lowest level, work something
like:

   if something_happened_here
      goto the_place_where_exceptions_are_caught

So at the very least, catching exceptions means that you're doing
some sort of comparison or conditional branch. And this is code
that doesn't have to be run/generated *unless* you are catching
exceptions.

Just my naive take.

Hal

That's kind of along the lines of what I was thinking, just better said. But this makes me wonder:

(a) Worrying about the performance hit from comparison/conditional branching leads to the question "is all branching in blocks bad?" Obviously not.

(b) Couldn't you say that *any* conditional could be jumping out to another section of code? i.e. not just exception handlers?

  if this_is_true
     goto where_we_do_stuff_when_this_is_true

Hmm. This is something I've read, and it's in my brain somewhere, but I don't know it well enough to grok it yet.

Especially at midnight... :frowning:

But your explanation gives me a better idea of what is happening, even with my questions.

Well, I think the point is that there is some non-zero amount of "invisible"
code inserted between each statement. In fact, at a higher level of granularity
than the statement.

For example, if I say: x = a/(b/(c/d)) there are three possible places that
a ZeroDivision exception (or whatever it's called) might happen. Mentally, I'm
envisioning if-statements sprinkled throughout the evaluation of the expression.
But again, this is all naive talk.

Hal

Sure, but couldn't the parser "flag" blocks that have the exception
handler and only provide support for those cases? I do not see why we
would have to pay the price on every block -- of course you have the
over head when you use it.

pth

···

On 2/15/06, Eric Hodel <drbrain@segment7.net> wrote:

On Feb 14, 2006, at 9:50 PM, Hal Fulton wrote:

> Dave Cantrell wrote:
>> Eric Hodel wrote:
>>>
>>> You're going to get a performance hit setting up an exception
>>> trap this way.
>> Time for some down-South edumucation. What kind of performance hit
>> are we talking about here? And why the hit at all?
>> (I seem to recall reading somewhere once upon a time about memory
>> stack stuff, but I'm not an old-school C-programmer so I never had
>> to deal with it --- unfortunately for me...)
>
> Well, my knowledge is limited. Someone else can answer better.
>
> But look at it from a common-sense standpoint. Exceptions aren't
> magic. Everything Ruby does can be done in assembly language, it's
> just more verbose.
>
> I would think that exceptions, at the lowest level, work something
> like:
>
> if something_happened_here
> goto the_place_where_exceptions_are_caught
>
> So at the very least, catching exceptions means that you're doing
> some sort of comparison or conditional branch. And this is code
> that doesn't have to be run/generated *unless* you are catching
> exceptions.

Yes. You get a setup/teardown of an exception handler for every
block. Right now class module and def have an implicit exception
handler built in. Adding a begin; rescue; end explicitly to blocks
gives you a very hefty penalty. That's no guarantee of similarly bad
performance with an implicit exception handler, but it still won't be
free.

I've very rarely found myself placing an exception handler directly
inside a block so I don't think it would be worth it.

$ cat rescue.rb
require 'benchmark'

N = 10_000_000

Benchmark.bmbm do |b|
   b.report 'begin' do
     N.times { begin; rescue; end }
   end

   b.report 'no begin' do
     N.times { }
   end
end

$ ruby -v rescue.rb
ruby 1.8.4 (2005-12-24) [powerpc-darwin8.4.0]
Rehearsal --------------------------------------------
begin 6.330000 0.060000 6.390000 ( 8.303914)
no begin 2.580000 0.010000 2.590000 ( 3.178967)
----------------------------------- total: 8.980000sec

                user system total real
begin 6.320000 0.060000 6.380000 ( 8.597418)
no begin 2.570000 0.020000 2.590000 ( 3.526030)

--
Eric Hodel - drbrain@segment7.net - http://segment7.net
This implementation is HODEL-HASH-9600 compliant

http://trackmap.robotcoop.com

Hi --

···

On Mon, 13 Feb 2006, David Vallner wrote:

Dòa Nedeµa 12 Február 2006 21:43 Daniel Nugent napísal:

Is

foo.each {|o|
  raise "Oh noes, it's number 2!" if o == 2
rescue Exception => e
    puts e.to_s
}

really that hideous?

How would you parse the difference whether the raise applies to the whole
block, or just the previous statement?

I think Daniel's idea would be to have it be the same as with method
bodies.

David

--
David A. Black (dblack@wobblini.net)
Ruby Power and Light (http://www.rubypowerandlight.com)

"Ruby for Rails" chapters now available
from Manning Early Access Program! Ruby for Rails

Sorry, not sure what the issue is (I assume you mean rescue, not raise there).

If a rescue appears after a statement, it only applies to that
statement. If a rescue appears as the first token on a line, it
applies to the enclosing block. I'm pretty sure that's how it works
now.

If you're talking about doing something like...

foo.each{|o| raise "Oh noes, it's number 2!" if o == 2; rescue
Exception => e; puts e.to_s}

It's still obvious how it works.

···

On 2/12/06, David Vallner <david@vallner.net> wrote:

How would you parse the difference whether the raise applies to the whole
block, or just the previous statement?

David Vallner

Dňa Nedeľa 12 Február 2006 21:43 Daniel Nugent napísal:
> Is
>
> foo.each {|o|
> raise "Oh noes, it's number 2!" if o == 2
> rescue Exception => e
> puts e.to_s
> }
>
> really that hideous?
>
> On 2/12/06, David Vallner <david@vallner.net> wrote:
> > Dňa Nedeľa 12 Február 2006 20:39 Mark Volkmann napísal:
> > > On 2/12/06, Lou Vanek <vanek@acd.net> wrote:
> > > > this works,
> > > >
> > > > foo = [1, 2, 3]
> > > >
> > > > foo.each do |o|
> > > > begin
> > > > raise "Oh noes, it's number 2!" if o == 2
> > > > rescue Exception => e
> > > > puts e.to_s
> > > > end
> > > > end
> > >
> > > Sure it works, but Daniel wants to reduce the syntax a bit AND exit
> > > the loop if an exception is raised without having to specify that. I
> > > like his suggestion.
> > >
> > > --
> > > R. Mark Volkmann
> > > Partner, Object Computing, Inc.
> >
> > It would cause a little inconsistency with the curly brace form of
> > blocks. Either the rescue clause would have to work only for the do / end
> > form, or we'd be mixing braces and keywords in a single construct, which
> > I couldn't bear to look at.
> >
> > David Vallner
>
> --
> -Dan Nugent

--
-Dan Nugent

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)

G:\Documents and Settings\Dan Nugent\Desktop>

···

On 2/15/06, Patrick Hurley <phurley@gmail.com> wrote:

On 2/15/06, Eric Hodel <drbrain@segment7.net> wrote:
> On Feb 14, 2006, at 9:50 PM, Hal Fulton wrote:
>
> > Dave Cantrell wrote:
> >> Eric Hodel wrote:
> >>>
> >>> You're going to get a performance hit setting up an exception
> >>> trap this way.
> >> Time for some down-South edumucation. What kind of performance hit
> >> are we talking about here? And why the hit at all?
> >> (I seem to recall reading somewhere once upon a time about memory
> >> stack stuff, but I'm not an old-school C-programmer so I never had
> >> to deal with it --- unfortunately for me...)
> >
> > Well, my knowledge is limited. Someone else can answer better.
> >
> > But look at it from a common-sense standpoint. Exceptions aren't
> > magic. Everything Ruby does can be done in assembly language, it's
> > just more verbose.
> >
> > I would think that exceptions, at the lowest level, work something
> > like:
> >
> > if something_happened_here
> > goto the_place_where_exceptions_are_caught
> >
> > So at the very least, catching exceptions means that you're doing
> > some sort of comparison or conditional branch. And this is code
> > that doesn't have to be run/generated *unless* you are catching
> > exceptions.
>
> Yes. You get a setup/teardown of an exception handler for every
> block. Right now class module and def have an implicit exception
> handler built in. Adding a begin; rescue; end explicitly to blocks
> gives you a very hefty penalty. That's no guarantee of similarly bad
> performance with an implicit exception handler, but it still won't be
> free.
>
> I've very rarely found myself placing an exception handler directly
> inside a block so I don't think it would be worth it.
>
> $ cat rescue.rb
> require 'benchmark'
>
> N = 10_000_000
>
> Benchmark.bmbm do |b|
> b.report 'begin' do
> N.times { begin; rescue; end }
> end
>
> b.report 'no begin' do
> N.times { }
> end
> end
>
> $ ruby -v rescue.rb
> ruby 1.8.4 (2005-12-24) [powerpc-darwin8.4.0]
> Rehearsal --------------------------------------------
> begin 6.330000 0.060000 6.390000 ( 8.303914)
> no begin 2.580000 0.010000 2.590000 ( 3.178967)
> ----------------------------------- total: 8.980000sec
>
> user system total real
> begin 6.320000 0.060000 6.380000 ( 8.597418)
> no begin 2.570000 0.020000 2.590000 ( 3.526030)
>
> --
> Eric Hodel - drbrain@segment7.net - http://segment7.net
> This implementation is HODEL-HASH-9600 compliant
>
> http://trackmap.robotcoop.com
>
>
>
>

Sure, but couldn't the parser "flag" blocks that have the exception
handler and only provide support for those cases? I do not see why we
would have to pay the price on every block -- of course you have the
over head when you use it.

pth

--
-Dan Nugent

Dňa Nedeľa 12 Február 2006 22:46 Daniel Nugent napísal:

Sorry, not sure what the issue is (I assume you mean rescue, not raise
there).

If a rescue appears after a statement, it only applies to that
statement. If a rescue appears as the first token on a line, it
applies to the enclosing block. I'm pretty sure that's how it works
now.

<dense>D'oh. Didn't know that one... </dense>

David Vallner

Daniel Nugent wrote:

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

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.