mscharrer has asked for the wisdom of the Perl Monks concerning the following question:

Hello,
I would like to use eval { } (i.e. the block version not the expression) quite often in one of my modules to protect for errors in function calls to other modules, i.e. exception handling.

I was just wondering how expensive the use of eval { } is. The code is compiled at compile time with all other code and eval can use the return statement, so it might be similar overhead like using a sub function.

Is eval {} much more expensive in terms of runtime (or other terms) then with e.g. using a sub call? Not that both would have the same function - just as a reference point.

Would it be ok, e.g. reasonable fast, to have eval {} inside a for loop, to test for exceptions for every element, or is it recommended to use eval {} outside the loop to speed things up?

Thanks for your wisdom.
Martin

Replies are listed 'Best First'.
Re: How expensive is eval { }?
by moritz (Cardinal) on Apr 17, 2008 at 09:12 UTC
    If you don't know, just try:
    use strict; use warnings; use Benchmark qw(cmpthese); no warnings 'void'; sub do_something { for (1..10){ $_*$_; } } cmpthese -1, { eval => sub { eval { for (1..10){$_*$_} } }, sub => sub { do_something() }, }; __END__ Rate sub eval sub 446836/s -- -0% eval 446836/s 0% --

    This is not a very good benchmark, but if eval BLOCK was very slow you'd see it here.

      Thanks,
      that's a good idea.

      I'm getting results from -3% to -6% in favor for sub on my machine. I might write a bigger benchmark and post the results here.

        I rerun the test several times and with different perl version (5.8.8 and 5.10.0), and got results from 0% to -4%.

        You can see that our both results have higher noise than the difference, so I wouldn't base a design decision on it. If exceptions are cleaner from a programming POV I'd go with exceptions.

Re: How expensive is eval { }?
by GrandFather (Saint) on Apr 17, 2008 at 09:19 UTC

    A simple benchmark indicates that the overhead isn't very much (unless the benchmark is completely flawed of course). Consider:

    use strict; use warnings; use Benchmark qw(cmpthese); cmpthese ( -1, { BareFor => \&dofor, ExceptFor => \&doefor, ForExcept => \&dofore, } ); sub dofor { my $sum = 0; for (1 .. 1000) { $sum += $_; $sum += $_; $sum += $_; } } sub dofore { my $sum = 0; for (1 .. 1000) { eval {$sum += $_;} } } sub doefor { my $sum = 0; eval { for (1 .. 1000) { $sum += $_; $sum += $_; $sum += $_; } } }

    Prints:

    Rate BareFor ExceptFor ForExcept BareFor 1626/s -- -2% -11% ExceptFor 1661/s 2% -- -9% ForExcept 1834/s 13% 10% --

    which indicates that the eval overhead is close to the cost of 2 += operations - not a whole lot in other words!


    Perl is environmentally friendly - it saves trees
      This benchmark result seems to vary strongly with the platform and/or perl version.

      Debian GNU/Linux i386 (32 bit, SMP):

      $ perl5.8.8 foo.pl Rate ForExcept BareFor ExceptFor ForExcept 2511/s -- -34% -34% BareFor 3794/s 51% -- -1% ExceptFor 3829/s 52% 1% -- $ perl5.10.0 foo.pl Rate ForExcept BareFor ExceptFor ForExcept 2393/s -- -29% -30% BareFor 3350/s 40% -- -2% ExceptFor 3429/s 43% 2% --

      That's quite different from the 2% .. 13%.

      Any idea why the differences between the perl versions and platforms are that big?

        No real idea, but bear in mind that most likely we are looking at only a few instructions' execution time difference between each case so they could be highly sensitive to optimization or modest differences in instruction timing between different processors (I ran my tests on a Turion64 powered laptop btw).

        Beyond indicating that the eval overhead is small enough to be discounted in most practical contexts, the benchmark really doesn't tell us very much - except that you can't trust benchmarks very much for this sort of fine grain comparison. The important thing to note is that the eval costs much less than 1 micro-second.


        Perl is environmentally friendly - it saves trees
Re: How expensive is eval { }?
by dragonchild (Archbishop) on Apr 17, 2008 at 12:35 UTC
    eval{} is about 30x faster than not using it. Of course, this assumes that your coding style is predisposed to using exceptions. Mine isn't, so eval{} is about 2x slower for me.

    Of course, I'm talking programmer speed. Execution speed matters very little when working in Perl. If it did, you wouldn't be working in Perl.


    My criteria for good software:
    1. Does it work?
    2. Can someone else come in, make a change, and be reasonably certain no bugs were introduced?
      I was actually talking about execution speed. I know Perl is not the fastest, but just wanted to know if the use of eval { } slows things down significantly. Eval remembers me a little on a fork which sounds runtime expensive if done very often.
      However the benchmarks in the other posts show that this is not the case, even if they are not very accurate.

      Thanks for your reply.