Perl,Alias子变量

时间:2017-11-16 13:10:10

标签: performance perl

我目前正在对perl程序进行微优化,并且喜欢优化一些getter。

我有一个包含此getter结构的包:

package Test;

our $ABC;

sub GetABC { $ABC } # exported sub...

调用GetABC()会产生大量与子相关的开销。直接通过$ Test :: ABC访问变量的速度非常快。

有没有办法将getter别名变量来获得与我直接调用变量相同的性能提升?用“()”内联提示似乎不起作用......

1 个答案:

答案 0 :(得分:5)

无法将变量转换为存取器子,或用可变访问替换子。你将不得不忍受开销。

非解决方案:

  • 使用()原型并不会将调用转入您的sub进行常量访问,因为该原型只会使子可能符合内联。由于sub的主体本身不是常数,因此该sub不能是常数。

  • 开销是每次通话,因为perl必须为每次通话进行大量的簿记。因此,在XS中重写该访问者将无济于事。

  • 创建constant无济于事,因为常量将是副本,而不是变量的别名。

但是看constant.pm source code似乎开辟了一个有趣的解决方案。请注意这是一个hack ,并且可能无法在所有版本的Perl中工作:当我们将标量引用直接分配给符号表条目时,该条目还没有包含typeglob,那么可以使用内联子弹簧到位:

package Foo;
use strict;
use warnings;
use feature 'say';

my $x = 7;
BEGIN { $Foo::{GetX} = \$x }  # don't try this at home
say GetX; #=> 7
$x = 3;
say GetX; #=> 3

目前适用于我安装的大多数perl版本(5.14,5.22,5.24,5.26)。但是,我的5.22-multi和5.26-multi die具有“尝试修改只读值”。这对于常量模块来说不是问题,因为它首先使参考目标首先读取,并且(更重要的是)永远不会修改该变量。

因此,这不仅不能可靠地工作,这也将完全弄乱不断的折叠。

如果函数调用开销确实无法忍受(例如占用处理时间的两位数百分比),那么在源代码中自行编入内容将是您最好的选择。即使您有很多呼叫位置,您也可以创建一个简单的脚本来修复容易的案例:选择导入模块的所有文件,并且只有一个package声明。在此类文件中,将对GetABC(带或不带有parens)的调用替换为完全限定的变量访问。希望在任何字符串中都没有提到该标记。之后,您可以手动检查这些呼叫的剩余几个。