我有一个长的 perl 脚本,它将文件中的一些信息缓存在哈希中,每隔一段时间(这里,每 100000 个位置),它会打印该窗口的哈希值,然后尝试删除大部分哈希中的内容,除了要在下一次迭代中使用的小缓冲区。
我说它试图删除内容,因为我的脚本在内存使用中爆炸,直到它使用所有内存并崩溃。尽管删除语句似乎将散列中的键数量(请参见下面的打印 STDERR)减少到只有少量元素,但脚本的内存消耗却猛增,就好像它没有删除内容一样。如果我注释掉 delete 语句,它使用相同数量的内存,唯一的区别是迭代需要更长的时间。似乎删除命令后键的数量减少了,但值的数量没有减少。
我确保结果的读取和输出没有奇怪的缓冲。事实上,如果我只是注释掉使用 %hash 的地方,脚本并不会耗尽内存,因此我将其范围缩小到填充和删除 %hash 中的条目。
我也尝试使用 hashref 而不是 %hash,同样的情况仍在发生。
怎么会在记忆中炸裂?我在这里遗漏了什么明显的东西吗?
my %hash;
# while ( Read from input ) {
# Fill hash here and there with: $hash{$this_p}{$this_c}++
# ...
# Then every 100000 entries
if ( not $pos % 100000 ) {
print STDERR "pre ", scalar %hash , "\n";
warn total_size(\%hash);
for my $p ( sort { $a <=> $b } keys %hash ) {
last if ( $p > $max_possible{$subset} );
if ( $p + $buffer < $pos ) {
print $out "$p\t";
for my $c ( keys %{ $hash{$p} } ) {
print $out "$c ". $hash{$p}{$c} . ";";
}
print $out "\n";
delete $hash{$p};
}
}
print STDERR "post ", scalar %hash , "\n";
warn total_size(\%hash);
}
#}
输出是这样的:
pre 322484/524288
134297952 at /home/
post 681/524288
4368924 at /home/av
pre 681/524288
4368924 at /home/av
post 681/524288
4368924 at /home/av
pre 681/524288
4368924 at /home/av
post 681/524288
4368924 at /home/av
pre 629257/1048576
260016542 at /home/
post 344/1048576
8477509 at /home/av
pre 1903885/4194304
689633878 at /home/
post 900/4194304
33790436 at /home/a
[...]
这是在 64 位 Linux 机器上使用 perl v5.14.2。