我正在尝试将use代码中的某些语句切换到require仅在满足某些条件时才使用的模块(例如,在需要这些模块的两次之间程序可能会加载 1,000 次),以降低开销并提高执行速度我的程序(我一直在使用 Devel::NYTProf 来分析我的代码,即使我没有在某个会话中使用它们,一些模块也会增加大量的执行时间)。
我遇到了一个问题,脚本在加载时终止,因为符号未定义(在导入该模块之前不会定义符号)。有没有办法告诉 Perl 符号将在运行时导入?一个简单的例子:如果我调用一个触发它的例程,我只想使用 Data::Dumper:
sub dataDumper {
require Data::Dumper;
Data::Dumper->import;
say STDERR Dumper @_;
}
Run Code Online (Sandbox Code Playgroud)
但是,调用Dumper第三行会导致异常。我可以通过参考来解决这个问题Data::Dumper->Dump。然而,LWP::UserAgent 的一个类似问题证明有点贴纸,因为 LWP::UserAgent 导入 HTTP::Request。我还没有想出my $request = new HTTP::Request GET => $params->{'url'};避免抛出异常的变体。
假设我可以这样做,有什么理由说明这种方法是个坏主意吗?通过在编译时不加载这些模块,我是否会失去任何类型的优化?在像 LWP 这样的模块上,这似乎是一个简单的调用——我只是不怎么使用它。我对是否尝试在(例如) Text::Textile 和 Text::MultiMarkdown 之间动态切换感到有些困惑(我通常每次执行只需要一个。
在 sub 调用中,只能为声明的 sub 省略参数周围的括号。
say STDERR Dumper(@_);
Run Code Online (Sandbox Code Playgroud)
请注意,您以这种方式加载的 subs 上的原型将被忽略。
第二行没有问题,因为它不涉及子调用。方法调用不受影响。
$ perl -M5.010 -e'
if ($ARGV[0]) {
require LWP::UserAgent; # or HTTP::Request
my $request = new HTTP::Request GET => "https://stackoverflow.com";
}
say "ok";
' 0
ok
$ perl -M5.010 -e'
if ($ARGV[0]) {
require LWP::UserAgent; # or HTTP::Request
my $request = new HTTP::Request GET => "https://stackoverflow.com";
}
say "ok";
' 1
ok
Run Code Online (Sandbox Code Playgroud)
因此,类模块在这里特别有用。考虑复杂情况下的插件模型。
通过在编译时不加载这些模块,我是否会失去任何类型的优化?
常量需要替换不能折叠的较慢的函数调用。
$ perl -MO=Concise,-exec -M5.010 -e'
use constant FOO => 2;
say 2 + FOO;
'
...
2 <;> nextstate(main 188 -e:3) v:{,fea=1
3 <0> pushmark s
4 <$> const[IV 4] s/FOLD
5 <@> say vK
...
Run Code Online (Sandbox Code Playgroud)
$ perl -MO=Concise,-exec -M5.010 -e'
say 2 + FOO();
require constant; import constant FOO => 2;
'
...
2 <;> nextstate(main 2 -e:2) v:{,fea=1
3 <0> pushmark s
4 <$> const[IV 2] s
5 <0> pushmark s
6 <#> gv[*FOO] s/EARLYCV
7 <1> entersub[t2] sKS/TARG
8 <2> add[t3] sK/2
9 <@> say vK
...
Run Code Online (Sandbox Code Playgroud)