ファイルからの情報をハッシュにキャッシュする長い perl スクリプトがあります。時々 (ここでは、100000 ポジションごとに)、そのウィンドウのハッシュの値を出力し、ほとんどのファイルを削除しようとします。次の反復で使用される小さなバッファーを除いて、ハッシュの内容。
私のスクリプトは、すべてのメモリを使用してクラッシュするまで、メモリ使用量が急増するため、コンテンツを削除しようとしていると言います。delete ステートメントがハッシュ内のキーの数を少数の要素に減らしているように見えても (以下の print STDERR を参照)、スクリプトのメモリ消費量はコンテンツを削除していないかのように急増します。delete ステートメントをコメント アウトすると、同じ量のメモリが使用されますが、唯一の違いは反復に時間がかかることです。削除コマンドの後にキーの数が減ったように見えますが、値の数は減っていません。
結果の読み取りと出力に奇妙なバッファリングがないことを確認しました。実際、%hash が使用されている場所をコメントアウトすれば、スクリプトはメモリ不足にならないので、%hash 内のエントリの入力と削除に絞り込みました。
また、%hash の代わりに hashref を使用しようとしましたが、同じことがまだ起こっています。
記憶に焼き付いているのはどうしてですか?ここで明らかな何かが欠けていますか?
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 を使用しています。