为什么当一个大数组被释放时,Perl不进行内存回收?

15

我知道 Perl 使用基于引用计数的垃圾回收机制。当一个变量超出作用域时,引用计数会减少,如果引用计数变为0,则内存被释放。 但是当我跟踪下面显示的一个小示例时,我无法找到内存释放的情况。

print "start..";

开始状态下的内存使用情况

sub func
{
    my $length = 8*1024*1024;
    my $array = [1..$length];

分配内存后的内存使用情况

}

func();

print "done..";

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

在这个例子中,当程序启动时,Perl.exe 占用大约 3MB 物理内存。 在 func() 调用期间进行分配后,Perl.exe 占用大约 370MB 内存。 但是,在 func() 调用之后,分配的内存应该被垃圾回收。为什么没有这样做呢?

期待您的回复。


3
如果你需要在Perl中重新分配大量内存,请fork一个子进程,为其分配内存,处理数据,然后退出该子进程。 - alex
2个回答

19
根据perlfaq3中的问题"如何释放数组或哈希表以使程序缩小?",以下是答案:
通常情况下是无法回收词法变量(即 my() 变量)分配的内存,即使它们超出了作用域也不能被重复利用。该内存保留以防变量重新进入作用域。全局变量分配的内存可以通过使用 undef() 和/或 delete() 重新使用(在程序内部)。在大多数操作系统上,分配给程序的内存永远不会返回到系统中。这就是为什么长时间运行的程序有时会重新执行自己的原因。一些操作系统(特别是使用 mmap(2) 分配大块内存的系统)可以回收不再使用的内存,但在这些系统上,必须配置和编译 Perl 使用操作系统的 malloc,而不是 Perl 自己的 malloc。总的来说,在 Perl 中,内存分配和释放不是你应该过多担心的事情。另请参见如何使我的 Perl 程序占用更少的内存?

哇,词法变量即使超出作用域也不会释放内存?我知道这适用于包变量,除非使用undef。我想这并不太糟糕,因为最大的数据块通常是使用引用完成的。 - David W.
7
Perl更看重性能而非小内存占用。你也可以对词法变量使用undef @a;,它会释放标量的底层和字符串缓冲区,并释放数组的底层数组。 - ikegami
6
如果再次执行func()函数,内存增加的数量并不明显。因此,我认为很清楚,当REFcount = 0时,Perl将内存标记为“未使用”,但从不将内存返回给操作系统。这些被标记为“未使用”的内存会在以后用于其他分配。 - InnovWelt

13

1
我之前也做了同样的事情(在看到你的答案之前 :)),我发现内存没有增加。所以,我回来告诉大家这个情况。但很高兴看到@DavidW已经指出了这一点。 - InnovWelt

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接