为什么在释放大型数组时Perl不会垃圾收集内存?

Inn*_*elt 14 perl memory-management

我知道Perl使用基于引用计数的垃圾收集.当变量超出范围时,引用计数递减,如果REFcount变为0,则取消分配内存.但是当我追踪下面显示的一个小例子时,我无法找到解除分配的情况.

print "start..";
Run Code Online (Sandbox Code Playgroud)

启动状态下的内存使用情况

sub func
{
    my $length = 8*1024*1024;
    my $array = [1..$length];
Run Code Online (Sandbox Code Playgroud)

分配后的内存使用情况

}

func();

print "done..";
Run Code Online (Sandbox Code Playgroud)

垃圾收集阶段的内存使用情况

在该示例中,当程序启动时,Perl.exe占用约3 MB的物理内存.在func()调用期间分配后,Perl.exe占用~370 MB内存.但是在func()调用之后,分配的内存应该被垃圾收集.为什么不这样做?

期待您的回复.

Jon*_*hop 18

根据问题" 如何释放数组或散列,以便我的程序缩小? "在perlfaq3中:

你通常不能.分配给词汇(即my()变量)的内存即使超出范围也无法回收或重用.如果变量返回范围,则保留它.分配给全局变量的内存可以通过使用undef()和/或delete()重用(在程序中).

在大多数操作系统上,分配给程序的内存永远不会返回给系统.这就是为什么长期运行的程序有时会重新执行的原因.某些操作系统(特别是使用mmap(2)分配大块内存的系统)可以回收不再使用的内存,但在这样的系统上,必须配置和编译perl以使用OS的malloc,而不是perl.

一般来说,内存分配和取消分配不是你可以或应该在Perl中担心的事情.

另请参见如何使我的Perl程序占用更少的内存?

  • Perl更喜欢小内存占用的性能.在词法上你总是可以`undef @a;`.它将释放标量的主体和字符串缓冲区,它将释放底层数组. (7认同)
  • 如果再次执行`func()`,则没有相当多的内存增加.所以我认为,很明显,如果REFcount = 0,Perl会将内存标记为"未使用",但永远不会将内存返回给OS.这个"未使用"标记的内存将来用于任何其他分配. (6认同)

Dav*_* W. 13

Perl可能已将内存标记为已释放,但并不一定意味着它已被释放回操作系统.您的Perl程序可能会重用该内存.再试func一次.您不应该看到使用的内存量增加.

您可能想要设置环境变量PERL_DESTRUCT_LEVEL,看看是否有任何区别,但我对此表示怀疑.

垃圾收集不是Perl最大的优势之一.