Perl 如何获得同样快速的命名子参数?

Perl 如何获得同样快速的命名子参数?,perl,Perl,perl sub的参数以@形式传递。为了使我的程序更易于阅读,我一直使用此模式获取命名参数: sub foo1 { my ($bar, $baz) = @_; do_something($bar,$baz); } 但是它会导致$\u0]和$\u1]被复制。如果我直接访问$\u0]而不是在上述模式中访问$bar,我可以通过值/别名访问调用者参数,并且通常需要注意通过引用调用,但速度要快得多(见下面的演示) 我有这样的怀疑,my($param1,$param2…)=@模式不好。所以

perl sub的参数以@形式传递。为了使我的程序更易于阅读,我一直使用此模式获取命名参数:

sub foo1 {
    my ($bar, $baz) = @_;
    do_something($bar,$baz);
}
但是它会导致
$\u0]
$\u1]
被复制。如果我直接访问
$\u0]
而不是在上述模式中访问
$bar
,我可以通过值/别名访问调用者参数,并且通常需要注意通过引用调用,但速度要快得多(见下面的演示)

我有这样的怀疑,
my($param1,$param2…)=@模式不好。所以我发现我必须在快速和可读的程序之间做出选择,这是一个不可能的选择

最后,我用
$\u[]
编写了以性能为中心的sub,并用上面的模式编写了其他所有sub。问题是,我常常事先不知道瓶颈在哪里;-)

有没有一种方法可以快速获取命名参数?或者佳能在这件事上做了什么<代码>$\[0]
$bar

附录:速度演示 打印出来

foo1 0.329470
foo2 1.280364

foo1的速度几乎是foo2的4倍,因为它避免了复制
$\u0]

通过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
}
坦率地说,我对性能优势有点怀疑(哈希访问不是免费的),但如果确实需要,您可以对其进行基准测试。但这并不是最好的性能选项(见下文),甚至可能不需要(见最后一部分),我认为这不太需要尝试


另一种选择(有点糟糕,但性能更好)是使用
$\u1]
等。。。但是通过大量的评论来对抗不可读性

           # pass `baz`
doSomething($_[1]);

另一个性能更高但设计不好的选项是绕过一起传递的参数,使用全局变量传递参数

our $bar = 1;
mySub();
sub mySub {
    #do something with $bar. Pray some other code didn't clobber it
}

最后考虑:

如果您的代码经过了很好的调优,并且对性能非常敏感,以至于复制两个标量会产生显著的差异,那么您可能希望将这些函数从Perl退出到纯C中

但是,正如Knuth所说,请不要过早地进行优化

首先,并确保标量参数复制确实是最大的瓶颈所在。我不认为这是合理的,但通常情况下,瓶颈在别处(IO、DB、慢速数据结构等)


换句话说,
$operation\u X
的实现速度可以提高4倍,如果
$operation\u X
占运行时间的0.01%,那么这一事实就没有任何意义。由于可读性降低,将其加速4倍根本不值得费心。

通过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
}
坦率地说,我对性能优势有点怀疑(哈希访问不是免费的),但如果确实需要,您可以对其进行基准测试。但这并不是最好的性能选项(见下文),甚至可能不需要(见最后一部分),我认为这不太需要尝试


另一种选择(有点糟糕,但性能更好)是使用
$\u1]
等。。。但是通过大量的评论来对抗不可读性

           # pass `baz`
doSomething($_[1]);

另一个性能更高但设计不好的选项是绕过一起传递的参数,使用全局变量传递参数

our $bar = 1;
mySub();
sub mySub {
    #do something with $bar. Pray some other code didn't clobber it
}

最后考虑:

如果您的代码经过了很好的调优,并且对性能非常敏感,以至于复制两个标量会产生显著的差异,那么您可能希望将这些函数从Perl退出到纯C中

但是,正如Knuth所说,请不要过早地进行优化

首先,并确保标量参数复制确实是最大的瓶颈所在。我不认为这是合理的,但通常情况下,瓶颈在别处(IO、DB、慢速数据结构等)


换句话说,
$operation\u X
的实现速度可以提高4倍,如果
$operation\u X
占运行时间的0.01%,那么这一事实就没有任何意义。由于可读性降低,将其加速4倍根本不值得费心。

好吧,如果您按此顺序通过$bar和$baz来sub do_something(),另一个不好的选择是使用以下可怕但有文档记录的语法:

sub foo1 { goto &do_something}
…这将传递上下文以立即执行某些操作。对记录参数没有帮助,但这可能是最快的传递到其他常规机制的方法。:-)


见鬼,我自己会否决这个答案….

好吧,如果你按顺序通过$bar和$baz来sub do_something(),另一个不好的选择是使用以下可怕但有记录的语法:

sub foo1 { goto &do_something}
…这将传递上下文以立即执行某些操作。对记录参数没有帮助,但这可能是最快的传递到其他常规机制的方法。:-)


见鬼,我自己会否决这个答案。

你可能也能玩一些别名技巧,但我从未使用过它们,对性能没有把握。是的,我也使用hashref方法,但对于具有一个或两个参数的sub,这对调用方来说会变得丑陋,例如
myEncode({str=>“foo”])
vs.
myEncode(“foo”)
。但它确实回答了这个问题…@PeterV.Mørch-对于具有1或2个参数的sub,使用第二种方法可能足够可读。非常难看,但如果性能如此关键……那么,如果您的代码经过了很好的调优,并且对性能非常敏感,以至于复制两个标量会产生影响,那么您可能希望退出对于这些函数,Perl转换为纯C。+1:操作_X的讨论很重要,我们需要务实。我接受了这个答案,因为它几乎证实了我迄今为止所采取的方法。我只是怀疑在我的应用程序中,将所有参数复制到所有sub可能需要大量超过%0.01的运行时间。你可能是