如何在Perl中释放内存?
我的代码如下所示:如何在Perl中释放内存?,perl,garbage-collection,Perl,Garbage Collection,我的代码如下所示: my %var; my %var_new={}; while(1){ while(my ($k,$v)=each %var){ &a_sub($v); } %var={}; # A map { $var{$_}=$var_new{$_}; } keys %var_new; %var_new={}; # B } sub a_sub { #....} # will fill %var_
my %var;
my %var_new={};
while(1){
while(my ($k,$v)=each %var){
&a_sub($v);
}
%var={}; # A
map { $var{$_}=$var_new{$_}; } keys %var_new;
%var_new={}; # B
}
sub a_sub { #....} # will fill %var_new
我的程序的内存使用率越来越高
Perl似乎没有在A行和B行释放内存
如何手动使Perl释放已使用的内存
%var
和%var\u new
?我认为使用undef
函数:
undef %var, %var_new;
也许能奏效。
当然,如果您不再需要那些散列中的内容如果您使用了
严格
和警告
,您会看到:
在预期大小为偶数的列表中找到引用
第A行和第B行并不像你想象的那样。实际上,它们将引用的字符串化版本指定为一个键,并将undef指定为其值。即使散列现在几乎为空,内存也不会被标记为可重用,因为您没有为此使用正确的语句
尝试在A行和B行使用以下语句之一:
undef %var; # this one
%var = (); # or this one
IIRC,一旦Perl从操作系统分配了内存,它就会在进程生命周期中保留该内存。在可能的情况下,Perl将重用已经分配的内存,而不是要求操作系统提供更多的内存,但是您不会看到进程使用的内存减少。可以通过
undef
将内存释放回操作系统。但是,$var=undef代码>和未定义($var)代码>
$var=undef代码>除了重置对象的标志外,不执行任何操作。大小还是一样
undf($var)
确实删除了指针并释放了该对象的内存-当且仅当这是“原始”变量时
有一个有趣的故事
例如,调用unde
(在Perl 5.30.0 Fedora 31、libc 2.30上测试)之后,下面的代码几乎回到了它最初的内存使用情况
即使遍历结构并对每个元素调用unde
,也是不够的(嵌套结构也是如此,您可以递归遍历它们,但不会有什么不同)
为什么??因为我们没有删除原始的$skilly
。将内存返回操作系统的唯一方法是调用unde($skelky)
如果像这样将$skilly
的引用放入%hash
中,$hash{large\u string\u inside}=\$skilly代码>
您仍然需要调用undef($skilly)
而不是undef($hash{large\u string\u inside})
为什么要将hashref分配给hash?使用strict;使用警告;使用diagnostics
(仅在开发过程中使用后者)尽管您发布的代码中存在bug,但没有理由让您发布的代码使用越来越多的内存,我认为这与其说是内存使用的问题,不如说是你已经建立了一个无限循环,从中没有逃逸。将%var
和%var\u new
设置为{}
应该有同样的效果。事实并非如此。使用Devel::Peek进行检查。@KeithThompson否,将%var
和%var\u new
设置为()
应具有相同的效果。取消定义散列将释放内存供perl进程内的其他用途,但不会减少进程使用的总内存。@chepner不正确。这完全取决于散列中的内容。如果不使用任何变量来填充哈希,例如$hash{thing}=“A”x 10000000代码>它将释放所有内存,并将内存返回操作系统。然而,如果你想做$hash{thing}=$var
,只有散列本身是免费的,但是由于$var
仍然是免费的,内存使用率可能会几乎保持不变。你所说的在实践中是正确的,但是Perl实际上可以将内存返回给操作系统。另一个问题是,在一般情况下,这是否可取。如何强制将未使用的内存释放到操作系统?是的。一旦一个进程从操作系统分配内存,它将一直保留到生命的尽头。它适用于任何语言,而不仅仅是Perl。也就是说,它编译Perl是为了使用mmap而不是它自己的malloc,只要内存完全未使用,就可以释放内存。@Luchostein,恕我直言,这不是真的<代码>perl-e'$a=“a”x100\u 000\u 000;对于(1..10){push@b,“$\$a”}睡眠10@b=();睡100;'代码>这将使用>1GB 10秒,然后再删除
#!perl
use feature 'say';
say "PID: $$";
say "Before Alloc";
<STDIN>;
my $large_string = "A" x 100000000;
say "After Alloc - Before undef";
<STDIN>;
undef($large_string);
say "After undef";
<STDIN>;
#!perl
use feature 'say';
use Devel::Peek;
$Devel::Peek::pv_limit = 15;
say "PID: $$";
say "BEFORE ALLOC";
<STDIN>;
my $sneaky = "A" x 100000000;
my %hash;
$hash{large_string_inside} = $sneaky;
say "After Alloc - Before undef";
say '$sneaky:';
Dump($sneaky);
say '%hash:';
Dump(%hash);
<STDIN>;
undef(%hash);
say "After undef";
say '$sneaky:';
Dump($sneaky);
say '%hash:';
Dump(%hash);
<STDIN>;
while(my ($k, $v) = each %hash) {
undef($v); # THIS IS NOT ENOUGH
}