in reply to eval string possibilities

Performance questions such as these can be answered empirically by using Benchmark. The accompanying POD describes its use.

The theory behind the performance difference will involve the fact that the string that you're evaling must be compiled at runtime, which will take a little time. Whether or not the time it takes is significant to your script's performance is another question. More often than not, the answer is ...not really. But you would have to profile a time-critical script to determine where the bottlenecks are before digging into how to optimize speed performance.

Common uses for eval strings are varied. One is to build a regexp on the fly. Another is to bring back to life something that was previously dumped via Data::Dumper (though the eval is often done behind the scenes via the same module).

And of course, any time that you find you really don't know how the code is supposed to come together until runtime string eval comes in handy (the regexp-on-the-fly is just one example).

For the most part, you won't need string eval, except when you really need it, and in those cases, it will seem natural (though it can be tricky getting metacharacters and quoting right).

eval is also useful, of course, for trapping errors, though often that's done using the block version of eval rather than the string version.

There is a really good chapter on eval in Advanced Perl Programming, published by O'Reilly & Associates (known as the Cougar book). It gives a few great examples.


Dave

Replies are listed 'Best First'.
Re^2: eval string possibilities
by erix (Prior) on Nov 22, 2004 at 04:36 UTC

    Yes, my specific question I could probably find out by testing myself, but I learned about Benchmark only a short while ago. It will probably be a little tricky to factor out things that are not related to the to-eval-or-not-eval question.

    And you are right; the little example is from the Cougar book, and my question springs from a program I started years ago based on it, and is still in use. It has grown (maybe even too much ;), and I find myself wondering what I will lose/gain by rewriting it.

    Thanks for your reply.

      I learned about Benchmark only a short while ago. It will probably be a little tricky to factor out things that are not related to the to-eval-or-not-eval question.

      In cases like this, I have learned that it's usually better to post bad code than no code at all. A small example written with Benchmark would have given repliers something to work with. They likely would have pointed out any flaws in the benchmark, and posted a modified version.

      There is a danger in this, though. Sometimes the code has small unrelated problems that derail the conversation, but I think this is a small price to pay. In my experience, posts containing pertinent code almost always get better replies.

      Sorry for the off-topic reply, but I think it will be useful for future posts. Hopefully you can avoid making some of the mistakes that I have made here at the Monastery. :-)

        Thanks for that advice, and I'll follow it up immediately with the script below, which I made after the OP and which is probably indeed bad code, although I think it does give the time discrepancies that I am looking for (qr much faster than eval). I suppose the main thing I missed all along (I had been told things in CB before), is the slowness of eval. Well, now I know :)

        #!/usr/bin/perl -w use strict; use warnings; use Benchmark qw /cmpthese/; cmpthese 10_000 => { 'do_eval' => sub { do_eval() }, 'do_qr' => sub { do_qr() }, }; sub do_eval { my $genome = "AGTATCGATCGATGCATGCTAGCTAGCTAGCTAGCTAGCTAGSTGCTAGCT"; my @regexes = ('abc', '^qwerty'); # dont care my $count = 0; my $code = 'if ($genome =~ /' . join ('/ && /', @regexes) . '/) { + $count++; }'; eval $code; die "Error: $@\n Code:\n$code\n" if ($@); } sub do_qr { my $string = "AGTATCGATCGATGCATGCTAGCTAGCTAGCTAGCTAGCTAGSTGCTAGCT"; my @regexes = ("abc", "^qwerty"); # dont care my $count = 0; my @compiled = map qr/$_/, @regexes; for(my $i=0; $i<@regexes; $i++) { if($string =~ /$compiled[$i]/){ $count++; } } } __END__ Rate do_eval do_qr do_eval 2162/s -- -77% do_qr 9242/s 328% --