我正在做一些非常大的數據的圖形分析,我需要存儲特定圖形邊緣的所有分數。鑑於數據的大小,我需要將信息寫入磁盤,並且我試圖使用與DBM::Deep並列的散列。以下是基本設置:如何正確地將散列與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方法是正確的。我改變了日誌模式,自動刷新,鎖定和其他設置,我看到了相同的行爲。
我在這裏使用DBM :: Deep不正確嗎?例如,我應該使用OO接口還是有更好的方法來編寫這種方法?
我會先發制人地說,很難提供一個示例文件來重現此問題,因爲腳本需要運行幾秒鐘才能發現泄漏(意味着文件必須至少有10萬行)。我希望有些東西會跳出來,但如果這些信息不夠,我會提供一個腳本和一些數據。我使用Perl v5.20.2和最新的DBM :: Deep,2.0011。
編輯:我已經簡化了代碼:
$match_pairs{$pair} = $score;
,我也曾嘗試OO接口做一個簡單的鍵/值存儲,我看到相同的行爲。這似乎是一個錯誤,所以我會報告它。
與您的問題完全無關,但您可能可以刪除除「push」行之外的所有行,並獲得相同的結果。 –
@JimDavis我讀到了autovivication不能正確的使用DBM :: Deep,或者不管用,所以我使用'if(exists $ hash {key}){...}'語法來保證安全。 – SES
我不知道。好吧! –