perl subs的参数在@_中传递.为了使我的程序更容易阅读,我总是使用这种模式来获取命名参数:
sub foo1 {
my ($bar, $baz) = @_;
do_something($bar,$baz);
}
Run Code Online (Sandbox Code Playgroud)
但它会导致$_[0]与$_[1]被复制.如果我是$_[0]直接访问而不是以$bar上述模式访问,我通过call-by-reference的常见警告对calllers参数进行call-by-value/alias访问,但速度要快得多(参见下面的演示).
我有这种怀疑,这种my ($param1, $param2 ...) = @_;模式因性能原因而不好.所以我发现我必须在快速和可读的程序之间做出选择,这是一个不可能的选择.
我最终编写了以性能为重点的子组件$_[<n>]以及上述模式的所有其他内容.麻烦的是,我经常不知道瓶颈在哪里;-)
有没有办法获得速度快的命名参数?或者似乎是关于此事的佳能?$_[0]还是$bar?
use Time::HiRes qw(time);
# Lets just do *something* with the parameters - here we just add up all
# their lengths
my $totalLength = 0;
sub foo1 {
# Access $_[0] directly - effectively call-by-reference
$totalLength += length($_[0]);
}
sub foo2 {
# Access a copy of $_[0] - effectively call-by-value - involves
# copying
my ($bar) = @_;
$totalLength += length($bar);
}
my $a = 'b' x 10_000;
my $t0 = time;
foreach (0..1_000_000) {
foo1($a);
}
printf "foo1 %2.6f\n", time - $t0;
$t0 = time;
foreach (0..1_000_000) {
foo2($a);
}
printf "foo2 %2.6f\n", time - $t0;
Run Code Online (Sandbox Code Playgroud)
打印出来
foo1 0.329470
foo2 1.280364
Run Code Online (Sandbox Code Playgroud)
foo1几乎比foo2快4倍,因为它避免了复制$_[0].
通过hashref传递它们:
my %args = (bar=>1, baz=>2);
mySub(\%args);
sub mySub {
my $args = shift;
doSomething($args); # pass entire parameter list for cheap!
doSomething2($args{bar}); # Use specific parameter
}
Run Code Online (Sandbox Code Playgroud)
坦率地说,我对性能优势有点怀疑(哈希访问不是免费的),但如果你真的需要,你可以对它进行基准测试.但这不是最好的性能选项(见下文),可能甚至不需要(见上一部分),而且我认为不需要尝试.
另一个选择(有点糟糕,但性能更好)是使用$_[1]等...但通过广泛的评论打击不可读性.
# pass `baz`
doSomething($_[1]);
Run Code Online (Sandbox Code Playgroud)
另一个性能更高但设计不好的选项是绕过参数传递,并使用全局变量传递参数.
our $bar = 1;
mySub();
sub mySub {
#do something with $bar. Pray some other code didn't clobber it
}
Run Code Online (Sandbox Code Playgroud)
最后考虑:
如果您的代码经过良好调整并且性能敏感,以至于复制几个标量会产生显着差异,那么您可能希望将Perl从Perl中删除为纯C来实现这些功能.
但是,正如Knuth所说,请不要过早优化.
首先,对整个应用程序进行概要分析,并确保标量参数复制确实是您最大的瓶颈所在.我不怀疑这是合理的,但通常,瓶颈在其他地方(IO,DB,慢速数据结构等......).
换句话说,如果$operation_X可以实现快4倍的事实,那么如果$operation_X占用运行时总数的0.01%则没有任何意义.如果降低可读性,那么加速4倍就不值得了.