Is 'rescue' expensive?

If i use something like:

array.count rescue array.size

does the rescue set up anything internally that will make this
inefficient ?

I have other options too, however, i want to minimize code clutter since
this situation is rare (my app says it works under 1.8.7 and 1.9).
Someones using it in 1.8.6 which i learn has no array#count. Otoh, 1.9
has no array#size.

Other options are :

unless Array.method_defined?(:count) then
class Array
def count
size
end
end
end

remark: i assume this is a one time startup cost

or:

if array.respond_to?(:count) then
array.count
else
array.size
end

remark: evaluated each time, so cost is high

My hope is that the rescue clause of the first example is only looked at
by the interpreter if an error occurs, otherwise there’s no penalty for
it.
Suggestions ?

El Martes, 12 de Enero de 2010, R. Kumar escribió:

If i use something like:

array.count rescue array.size

does the rescue set up anything internally that will make this
inefficient ?

I have other options too, however, i want to minimize code clutter since
this situation is rare (my app says it works under 1.8.7 and 1.9).
Someones using it in 1.8.6 which i learn has no array#count. Otoh, 1.9
has no array#size.

Ruby 1.9 has Array#size, sure.

My hope is that the rescue clause of the first example is only looked at
by the interpreter if an error occurs, otherwise there’s no penalty for
it.
Suggestions ?

Forgetting the fact tha Array#size does exist iunder 1.9, I think that
defining the method “count” (in case it doesn’t exist) is a bit faster:

Ruby allows redefining methods in runtime which means that when a method
is
invoked the interpreter must look for it and execute its code. Then:

array.count rescue array.size

  • First it involves looking for “count” method.

  • It doesn’t exist so raises.

  • Then “size” is invoked so it involves looking for “size” method.

    unless Array.method_defined?(:count) then
    class Array
    def count
    size
    end
    end
    end

In this case:

  • First “count” is looked for.
  • It’s found and “size” is invoked so “size” method is looked for.

It’s faster as you avoid the rescue.

Iñaki Baz C. wrote:

El Martes, 12 de Enero de 2010, R. Kumar escribió:
Ruby 1.9 has Array#size, sure.

I looked at http://yardoc.org/docs/ruby-core/Array and it did not show a
size method.
Perhaps that’s been aliased and the doc does not report aliases. Best
thing is for me to try it in 1.9!

El Martes, 12 de Enero de 2010, R. Kumar escribió:

Iñaki Baz C. wrote:

El Martes, 12 de Enero de 2010, R. Kumar escribió:
Ruby 1.9 has Array#size, sure.

I looked at http://yardoc.org/docs/ruby-core/Array and it did not show a
size method.
Perhaps that’s been aliased and the doc does not report aliases. Best
thing is for me to try it in 1.9!

irb(main):023:0> RUBY_VERSION
“1.9.1”

irb(main):025:0> RUBY_PATCHLEVEL
376

irb(main):024:0> [].size
0

:slight_smile:

Iñaki Baz C. wrote:

El Martes, 12 de Enero de 2010, R. Kumar escribió:

Iñaki Baz C. wrote:

El Martes, 12 de Enero de 2010, R. Kumar escribió:
Ruby 1.9 has Array#size, sure.

I looked at http://yardoc.org/docs/ruby-core/Array and it did not show a
size method.
Perhaps that’s been aliased and the doc does not report aliases. Best
thing is for me to try it in 1.9!

irb(main):023:0> RUBY_VERSION
“1.9.1”

irb(main):025:0> RUBY_PATCHLEVEL
376

irb(main):024:0> [].size
0

:slight_smile:

Yes, i just checked myself. “size” matters :-).

If in 99 pc cases, “count” works, then the rescue is only read by the
interpreter in the 1% case where it fails. Is that right?

(Anyway, for this particular case, i am changing count to size)

El Martes, 12 de Enero de 2010, R. Kumar escribió:

Yes, i just checked myself. “size” matters :-).

If in 99 pc cases, “count” works, then the rescue is only read by the
interpreter in the 1% case where it fails. Is that right?

IMHO yes

On Tue, Jan 12, 2010 at 6:07 AM, R. Kumar [email protected] wrote:

If i use something like:

array.count rescue array.size

does the rescue set up anything internally that will make this
inefficient ?

To address the original question, the use of rescue does impart a
small overhead, but unless you are min-maxing performance in a tight
loop somewhere, you can safely disregard the amount of overhead. This
is also something you can readily test for yourself, BTW:

Benchmark.bm {|bm| bm.report {10000000.times {a.size rescue ‘stuff’}}}
user system total real
1.480000 0.000000 1.480000 ( 1.476450)

Benchmark.bm {|bm| bm.report {10000000.times {a.size}}}
user system total real
1.280000 0.000000 1.280000 ( 1.283498)

Kirk H.

El Martes, 12 de Enero de 2010, Iñaki Baz C. escribió:

El Martes, 12 de Enero de 2010, R. Kumar escribió:

Yes, i just checked myself. “size” matters :-).

If in 99 pc cases, “count” works, then the rescue is only read by the
interpreter in the 1% case where it fails. Is that right?

IMHO yes

…but I was wrong as Kirk has explained in a new thread :slight_smile:

Albert S. wrote:

It’d be faster if you use the ‘alias’ keyword instead of wrapping the
call in a function of your own because then you save one function call.

Thanks a lot for your answer. This brings up a question on usage of
“rescue”. Is it a “code smell” or bad programming?

I recall i’ve used it in some places where often different datatypes can
come in. Forgetting this, over time , I’ve added a “.length()” check or
“.trim()”, “chomp()” etc.

Suddenly, when boolean data or Fixnum comes these lines fail, so I tend
to add a rescue clause. And these are typically in a loop.
Currently, the “rescue” would work for various cases and datatypes. If I
open classes and start adding aliases or methods, I could have to do it
over and over again.

I would appreciate some guidelines on rescue usage.

R. Kumar wrote:

If i use something like:

array.count rescue array.size

does the rescue set up anything internally that will make this
inefficient ?

rescue’s impact is negligible.

HOWEVER, that’s NOT the question you need to ask. You need to ask how
costly is hitting on a nonexistent method. See my benchmark (I do have
Array#size on my system):

Benchmark.bm {|bm| bm.report {100000.times {a.size rescue a.size}}}
user system total real
0.110000 0.000000 0.110000 ( 0.219765)

Benchmark.bm {|bm| bm.report {100000.times {a.not_found rescue a.size}}}
user system total real
30.450000 0.520000 30.970000 ( 33.876875)

See? On my system, hitting a nonexistent method is 300 times slower than
existing one.

Other options are :

unless Array.method_defined?(:count) then
class Array
def count
size
end
end
end

It’d be faster if you use the ‘alias’ keyword instead of wrapping the
call in a function of your own because then you save one function call.

One of the things that seems to be mostly missing from this discussion
(which after all started out with dealing with a difference between
Ruby 1.8 and 1.9, is that since Ruby class definitions are executable,
you can move the overhead to class definition time with code like

class Foo
def some_version_independent method
#…
end
if RUBY_VERSION =~ /^1.9/
def some_version_dependent_method
#implementation which works in 1.9
end
else
def some_version_dependent_method
#implementation which works in 1.8
end
end
end


Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: Rick DeNatale - Developer - IBM | LinkedIn

On Wed, Jan 13, 2010 at 12:11 AM, R. Kumar [email protected]
wrote:

Albert S. wrote:

It’d be faster if you use the ‘alias’ keyword instead of wrapping the
call in a function of your own because then you save one function call.

Thanks a lot for your answer. This brings up a question on usage of
“rescue”. Is it a “code smell” or bad programming?

“Code smell” is a weak concept that people use when they can’t give
clear, concise reasons why they don’t like something about a piece of
code.

There is nothing wrong with “rescue”. It’s an essential part of
writing good code, in fact. That doesn’t mean it can’t be misused,
though.

I recall i’ve used it in some places where often different datatypes can
come in. Forgetting this, over time , I’ve added a “.length()” check or
“.trim()”, “chomp()” etc.

You can use a respond_to? check in your code to see if you are dealing
with an object that supplies the methods you are expecting. This is
often more useful than just calling a method and rescuing its failure.

Also, one thing to be aware of is that while a rescue clause itself
confers only a modest overhead, if you are actually triggering
exceptions that are rescued often, that confers a substantial
overhead. There are some time consuming things, such as constructing
the backtrace, that go into exceptions, so the fewer exceptions your
code raises, the better, generally.

Suddenly, when boolean data or Fixnum comes these lines fail, so I tend
to add a rescue clause. And these are typically in a loop.
Currently, the “rescue” would work for various cases and datatypes. If I
open classes and start adding aliases or methods, I could have to do it
over and over again.

There isn’t a clear, well defined answer to this. It really depends
on the architecture of your overall code. I would suggest, though,
that if you end up having a lot of lines with rescue clauses at the
end of them, you are probably doing something wrong and need to step
back and look at how you can adjust your code to consolidate the
places where you employ rescue clauses, whether that’s by making your
code smarter elsewhere, or by using the begin/rescue/end(else) syntax
to apply a single rescue clause to a broader swath of code.

Kirk H.