gpt4 book ai didi

即使在执行删除操作时,perl 内存也会在散列中膨胀?

转载 作者:行者123 更新时间:2023-12-04 18:43:56 25 4
gpt4 key购买 nike

我有一个很长的 perl 脚本,可以从文件中缓存一些信息
在散列中,每隔一段时间(这里,每 100000 个位置),
它打印该窗口的哈希值,然后尝试
从散列中删除大部分内容,除了一个小缓冲区
在下一次迭代中使用。

我说它试图删除内容,因为我的脚本炸了
在内存使用中,直到它使用所有内存并崩溃。尽管它
似乎删除语句正在减少哈希中的键数
(请参阅下面的打印 STDERR)只有少数元素,
脚本的内存消耗猛增,就好像它没有删除一样
内容。如果我注释掉删除语句,它使用相同的
内存量,唯一的区别是需要更长的时间
迭代。删除后好像键数减少了
命令,但不是值的数量。

我确保阅读没有奇怪的缓冲,并且
结果的输出。事实上,脚本不会耗尽​​内存,如果
我只是注释掉使用 %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。

最佳答案

随着程序运行,您在每次传递中放置在散列中的元素数量会增加。 0+keys(%hash)会告诉你确切的数字,但下面的分子将相似(但更低)

                      322484 added
pre 322484/524288
321803 cleared (99.8% of added)
post 681/524288
0 added
pre 681/524288
0 cleared (100.0% of added)
post 681/524288
0 added
pre 681/524288
0 cleared (100.0% of added)
post 681/524288
628576 added
pre 629257/1048576
628913 cleared (100.0% of added)
post 344/1048576
1903541 added
pre 1903885/4194304
1902641 cleared (100.0% of added)
post 900/4194304

分母增长只是因为分子在增长。这无关紧要。这不是累积增长。即使你每次都有一个新的哈希,它也会变得那么大。

分子只会增长,因为您添加到散列的元素数量在增长。如您所见,清算代码非常有效。

这看起来根本不像是内存泄漏;看起来您实际上正在使用内存。也许你应该更频繁地清除它?

代替
if (not $pos % 100000) {
...
}


if (keys(%hash) >= 1_000_000) {
...
}

或者,如果您想要定期反馈,
if (++$since_last >= 100_000 || keys(%hash) >= 1_000_000) {
$since_last = 0;
...
}

根据需要调整限制。

关于即使在执行删除操作时,perl 内存也会在散列中膨胀?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18210815/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com