Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Perl: Speeding up eval

Tags:

perl

eval

eval is slow when done on a string: The string first has to be parsed before it can be executed.

I am looking for a way to cache the parsing, so that I can reuse the parsed string for yet another eval. The next eval will be the same code, but will not eval to the same value, so I cannot simply cache the results.

From the description I am looking for ceval from Eval::Compile.

But I cannot use Eval::Compile, as that requires a C compiler for the platform, and it is not given that the user has a C compiler.

So can I do something similar to ceval in pure Perl?

Background

GNU Parallel lets the user give Perl expressions that will be eval'ed on every argument. Currently the Perl expressions are given as strings by the user and eval'ed for every argument. The Perl expressions remain unchanged for each argument. It is therefore a waste to recompile the expression as the recompilation will not change anything.

Profiling of the code shows that the eval is one of the bottlenecks.

Example

The user enters: $_ .= "foo" and s/a/b/g

A user's scripts are stored in $usereval1 and $usereval2.

The user gives 10000 random arguments (strings) stored in @arguments.

sub replace {
  my ($script, $arg) = @_;
   local $_;
   $_ = $arg;
   # This is where I would like to cache the parsed $script.
   eval $script;
   return $_;
}

for my $arg (@arguments) {
   # Loads of indirect code (in the order of 1000 lines) that
   # call subs calling subs calling subs that eventually does:
   $replaced1 = replace($usereval1, $arg);
   $replaced2 = replace($usereval2, $arg);
   # Yet more code that does stuff with $replaced1 $replaced2
}
like image 440
Ole Tange Avatar asked Feb 24 '26 10:02

Ole Tange


1 Answers

You can store a subroutine ref like this:

perl -lwe 'my $x = eval(q( sub { my $foo = shift; $foo*2; } )); print $x->(12);'

This prints 24. You can reuse the code without the need to recompile it.

like image 78
TLP Avatar answered Feb 27 '26 01:02

TLP