Perl:加快评估 [英] Perl: Speeding up eval

查看:109
本文介绍了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.

从描述中我正在寻找ceval的来源: https://metacpan.org/pod /Eval :: Compile

From the description I am looking for ceval from: https://metacpan.org/pod/Eval::Compile

但是我不能使用Eval :: Compile,因为这需要平台使用C编译器,并且不能认为用户拥有C编译器.

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.

那么我可以在纯Perl中做类似于ceval的事情吗?

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

背景

GNU Parallel允许用户给出将在每个参数上评估的perl表达式.目前,perl表达式由用户以字符串形式给出,并针对每个参数进行评估.每个参数的perl表达式均保持不变.因此,重新编译表达式是浪费的,因为重新编译不会改变任何内容.

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 re-compile the expression as the re-compilation will not change anything.

对代码进行概要分析表明,eval是瓶颈之一.

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

示例

用户输入:$_ .= "foo" and s/a/b/g

用户的脚本存储在$usereval1$usereval2

用户提供了@arguments中存储的10000个随机参数(字符串).

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
}

推荐答案

根据请求发布评论作为答案:

Posting comment as answer per request:

您可以像这样存储子例程ref:

You can store a subroutine ref like this:

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

这将打印24.您可以重新使用代码,而无需重新编译.

This prints 24. You can re-use the code without the need to recompile it.

这篇关于Perl:加快评估的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆