我正在对一些非常大的数据进行图形分析,我需要存储特定图形边缘集的所有分数。鉴于数据的大小,我需要将信息写入磁盘,并尝试使用DBM::Deep的绑定哈希。这是基本设置:
#!/usr/bin/env perl
use 5.010;
use strict;
use warnings;
use autodie;
use File::Spec;
use DBM::Deep;
use Cwd;
my $file = shift;
my $wd = getcwd();
open my $fh, '<', $file;
my %match_pairs;
my $dbm = File::Spec->catfile($wd, "pairs.dbm");
unlink $dbm if -e $dbm;
tie %match_pairs, 'DBM::Deep', {
file => $dbm,
locking => 1,
autoflush => 1,
type => DBM::Deep::TYPE_HASH
};
然后,我解析文件并将信息存储在某个分数阈值之上,如此($pair
只是一个常规字符串):
if (exists $match_pairs{$pair}) {
push @{$match_pairs{$pair}}, $score;
}
else {
$match_pairs{$pair} = [$score];
}
此代码会产生内存泄漏,直到您终止进程为止。如果我注释掉这六行,没有内存泄漏。奇怪的是数据被写入DBM文件,当我使用DBM :: Deep时,我得到相同的结果,所以看起来tie方法是正确的。我已经更改了日志模式,autoflush,锁定和其他设置,我看到了相同的行为。
我在这里使用DBM :: Deep不正确吗?例如,我应该使用OO接口还是有更好的方法来编写此方法?
我会先发制人地说很难提供一个示例文件来重现这个问题,因为脚本需要运行几秒才能注意到泄漏(意味着文件必须至少有100k行)。我希望有些东西会跳出来,但如果这些信息不够,我会提供一个脚本和一些数据。我使用的是Perl v5.20.2和最新的DBM :: Deep,2.0011。
编辑:我已将代码简化为:
$match_pairs{$pair} = $score;
我也尝试过OO接口做一个简单的键/值存储,我看到了相同的行为。看来这肯定是一个错误所以我会报告它。
答案 0 :(得分:1)
我在相关的GH问题中回答了这个问题(谢谢你打开它!),但我会在这里重复一遍。
是的,随着时间的推移,RAM的数量会逐渐上升。当将/usr/dict/words
作为密钥读入DBM :: Deep哈希(Ubuntu 14.04,Perl 5.22.0)时,对于每30k字读取,我的RAM上升约1k。我的猜测(没有可重复的测试)是这只是簿记DBM :: Deep需要跟踪添加30k元素所需的额外数据级别。
正如我在该问题的评论中所提到的,如果有可重复的测试文件,我可以对项目进行更深入的研究。