Lum*_*umi 2 memory perl function
在这里出现一个邋,,非实际的问题.您知道在Perl中,您可以将子例程存储在变量中,例如Javascript和其他语言.子程序确实占用了一些内存.
现在您可能会认为它会节省内存以使用对子例程的一个引用来为各种包中的许多相同子例程提供实现.像所有那些制定者和吸气者一样.(是的,我应该使用其中一个现有的mooses或老鼠或诸如此类的东西,但这是一个非实际的问题.)或者像你可能想要在各种包中使用的其他例程一样,以使所有这些包能够做一些横切跆拳道.
你可以让每个班级的代表来完成这项工作.但也许这太重了太OO.你想要子程序.也许这被称为混合?无论如何,你想在每个包中安装一个子程序,认为它可以节省内存,你可以测试一行,如下所示:
perl -lwe "$s=sub { print 33 };
for (1 .. 20000) { $p=qq(Bla${_}::bla); *$p = $s} Bla987::bla(); <>"
Run Code Online (Sandbox Code Playgroud)
(好吧,它在这里有两行来容纳页面宽度.请注意,在Windows上需要双引号,而在Linux上,你使用单引号来避免shell吃掉你的钱.)
现在,这个有趣的代码(质量可疑,仅用于演示目的)确实创建了20,000个包并在每个包中安装该子例程(在相应的符号表条目中).
根据我创建的软件包数量,我可以看到内存消耗在{{taskmgr}}中上下变化(20,000个软件包为12.2 KB,10,000个软件包为6.7,100个软件包为1.0 KB - 不是很多,总而言之),但是我想这不是因为sub被复制,而是因为创建了额外的包.
那是对的吗?子没有被复制,它只被引用?
关于这个话题有什么好的阅读?或者这是冒险实现细节和perl5porters的东西?
或者这里的整个思路只是误导了沉思和疑惑?
更新
好吧,我不确定{{$ s}}中的{{sub}}是否被重用 - 因为当我在循环中创建新的子程序时,内存使用率不会上升:
perl -lwe "for (1 .. 20000) {
$p=qq(Bla${_}::bla); *$p = sub {print 33} } Bla987::bla(); <>"
Run Code Online (Sandbox Code Playgroud)
但也许这是因为sub是不变的.
如果我在子中引入变量元素,内存使用率会上升(10,000个包的10 KB和20,000的20 KB),如下所示:
perl -lwe "for my $i (1 .. 10000) {
$p=qq(Bla${i}::bla); *$p = sub {print $i} } Bla987::bla(); <>"
Run Code Online (Sandbox Code Playgroud)
Perl只会编译子程序一次.您正在传递对它的引用,如果您检查地址,它将是相同的.
内存泄漏来自创建20,000个包,这些包是20,000个哈希引用,每个包含一些魔法需要更多的内存.每个哈希引用都包含带有子例程名称的字符串的副本.每个哈希的引用都放在main::符号表中.
如果您希望子程序在所有包中的范围内,请使用完全限定名称,将子例程放入跨越所有包的词法中,或将子例程放入符号变量中:
sub some::name {} # call as `some::name()` from anywhere
my $x = sub {}; # call as `$x->()` anywhere $x is in scope
*! = sub {}; # call as `&!()` from anywhere
Run Code Online (Sandbox Code Playgroud)
上述任何一种解决方案都可以让您从其他软件包访问,而不会浪费大量内存.
根据您的更新,您看到闭包大小增加,因为虽然每个subref相同,但每个都必须创建一个新的词法填充来保存闭包变量,这对于每个闭包都是唯一的.
您也可以使用UNIVERSAL包在任何地方使用方法,但它可能会有问题,所以请注意以下几点:
sub UNIVERSAL::foo {say "foo(@_)"}
xyz->foo; # foo(xyz)
Run Code Online (Sandbox Code Playgroud)