2013-08-13 7 views
5

私は、ファイル からいくつかの情報をキャッシュに入れた長いperlスクリプトを持っています。そして、たびに(ここでは、100000の位置ごとに)、 はそのウィンドウのハッシュの値を表示し、 には、次の反復で使用される小さなバッファ を除いて、ほとんどのコンテンツがハッシュから削除されます。削除してもペールメモリがハッシュで膨らんでいますか?

すべてのメモリとクラッシュが使用されるまで、私のスクリプトはメモリ使用量が であるため、内容を削除しようとしています。それ は、それが 内容を削除されていないかのようにdelete文は、要素のほんの数、スクリプト急騰の メモリ消費に(下の印刷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); 
    } 
#} 

出力は次のようなものである:これは64ビットのLinuxボックス上のperl v5.14.2を使用している

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 
[...] 

+0

ハッシュの要素を削除すると、割り当てられたバケットがリセットされていないようです。 'perl -le '$ min = 0; $ max = shift; %a = map $ _ => 1、$ min .. $ max; for(1 .. $ max - 10){delete $ a {$ _}};スカラーを出力する%a '1000001'出力: '5/524288'代わりにキー/値をコピーしてみてください。 – TLP

+0

@TLPキー/値をコピーしていますか? – 719016

+0

古いものをコピーして新しいハッシュを作成し、古いものを範囲外にします。 – mirod

答えて

6

各パスでハッシュに配置する要素の数は、プログラムの実行中に増加しています。分子が成長しているので、分母が唯一成長している

     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 

0+keys(%hash)はあなたの正確な数を言うだろうが、以下の分子は、類似した(しかし、下)になります。それは関係ない。それは累積的な成長ではありません。それは毎回新鮮なハッシュを持っていてもそれを大きくするでしょう。

分子が増加するのは、ハッシュに追加する要素の数が増えるためです。ご覧のとおり、クリアコードは非常にうまく機能します。

これはメモリリークのようには見えません。実際にメモリを使用しているようです。多分それをもっと頻繁にクリアするべきでしょうか?

代わりの

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

使用

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

それとも、定期的なフィードバックをしたい場合は、必要に応じ、

if (++$since_last >= 100_000 || keys(%hash) >= 1_000_000) { 
    $since_last = 0; 
    ... 
} 

が制限を調整します。

関連する問題