Performance Perl,别名sub to变量

Performance Perl,别名sub to变量,performance,perl,Performance,Perl,我目前正在对一个perl程序进行微优化,并喜欢优化一些getter 我有一个具有此getter结构的包: package Test; our $ABC; sub GetABC { $ABC } # exported sub... 调用GetABC()会产生大量子相关的开销。通过$Test::ABC直接访问变量的速度快得惊人 有没有一种方法可以将getter别名为变量以获得与直接调用变量相同的PerformanceBost?用“()”内联提示似乎不起作用…无法将变量转换为访问器子项,或用变量

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

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

package Test;

our $ABC;

sub GetABC { $ABC } # exported sub...
调用GetABC()会产生大量子相关的开销。通过$Test::ABC直接访问变量的速度快得惊人


有没有一种方法可以将getter别名为变量以获得与直接调用变量相同的PerformanceBost?用“()”内联提示似乎不起作用…

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

非解决方案:

  • 使用
    ()
    原型不会将调用转换为sub-to-constant访问,因为该原型只会使sub可能符合内联条件。由于接头主体本身不是常数,因此此接头不能是常数

  • 开销是每个调用的开销,因为perl必须为每个调用做大量的簿记。因此,在XS中重写该访问器不会有多大帮助

  • 创建
    常量
    没有帮助,因为该常量是变量的副本,而不是别名

但看看这个问题似乎可以找到一个有趣的解决方案。请注意,这是一个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模具带有“试图修改只读值”。这对于常量模块来说不是问题,因为它首先使引用目标为只读,并且(更重要的是)从不修改该变量

因此,这不仅不能可靠地工作,而且还将彻底破坏持续的折叠。



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

无法将变量转换为访问器sub,或将sub替换为变量访问。你将不得不忍受开销

非解决方案:

  • 使用
    ()
    原型不会将调用转换为sub-to-constant访问,因为该原型只会使sub可能符合内联条件。由于接头主体本身不是常数,因此此接头不能是常数

  • 开销是每个调用的开销,因为perl必须为每个调用做大量的簿记。因此,在XS中重写该访问器不会有多大帮助

  • 创建
    常量
    没有帮助,因为该常量是变量的副本,而不是别名

但看看这个问题似乎可以找到一个有趣的解决方案。请注意,这是一个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模具带有“试图修改只读值”。这对于常量模块来说不是问题,因为它首先使引用目标为只读,并且(更重要的是)从不修改该变量

因此,这不仅不能可靠地工作,而且还将彻底破坏持续的折叠。



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

您多久进行一次这样的检查,以确定差异是否真正重要?大约100k:-)差异为30-40ms(这在我当前的场景中非常大)。是否可以将值导入到当前命名空间中?仅仅参考
$Test::ABC
,有什么问题吗?我觉得奇怪的是,您谈论的是如此深层次的语言特性,但您在代码示例中使用了错误的注释语法olol确实:D fixed您多长时间这样做一次,差异才是真正重要的?大约100k:-)这是30-40ms的差异(这对于我当前的场景来说是相当大的)。也许将值导入当前名称空间?仅仅参考
$Test::ABC
,有什么问题吗?我觉得奇怪的是,您谈论的是如此深层次的语言特性,但您在代码示例中使用了错误的注释语法奥洛尔:我非常感谢这个非常好的答案。我的5.12.3-multi也不允许写入该变量。。。我尝试了好几个小时的不同的东西,现在没有任何运气。搜索并替换所有包中的方法调用是这里的最佳答案(在