2013-08-16 7 views
6

私はSTの中にData.Vector.Unboxed.Mutableを通してメモリを割り当てる計算をしています。このベクトルは決して読み込まれたり書かれたりすることはありません。私が持っている問題は、私がST計算を何度も実行すると、時にはベクトルの周りのメモリを保持しているように見えることです。Haskell:ST/GCからのメモリリークは収集されませんか?

アロケーション統計:

5,435,386,768 bytes allocated in the heap 
    5,313,968 bytes copied during GC 
    134,364,780 bytes maximum residency (14 sample(s)) 
    3,160,340 bytes maximum slop 
      518 MB total memory in use (0 MB lost due to fragmentation) 

ここで私は私の計算と128MBのベクトルの異なる値でrunST 20倍呼び出す(再び - 、未使用のSTの外に返されたり参照されていません)。最大限のレジデンスは、基本的に私のベクトルプラス数MBの他のものを加えて、よく見えます。しかし、全体のメモリ使用量は、同時に4つのベクトルコピーがアクティブであることを示しています。これはベクトルのサイズに完全に比例します。256MBの場合、予想どおり1030MBが得られます。

1GBのベクトルを使用するとメモリが不足します(4x1GB +オーバーヘッド> 32ビット)。私は、RTSが、少なくとも割当てが失敗した時点で、GC'ingの代わりに、未使用の未参照のメモリを周りに残している理由を理解していません。 + RTS -Sで実行

は、次のことを明らかに:

ここ
Alloc Copied  Live GC GC  TOT  TOT Page Flts 
    bytes  bytes  bytes user elap user elap 
134940616  13056 134353540 0.00 0.00 0.09 0.19 0 0 (Gen: 1) 
    583416  6756 134347504 0.00 0.00 0.09 0.19 0 0 (Gen: 0) 
    518020  17396 134349640 0.00 0.00 0.09 0.19 0 0 (Gen: 1) 
    521104  13032 134359988 0.00 0.00 0.09 0.19 0 0 (Gen: 0) 
    520972  1344 134360752 0.00 0.00 0.09 0.19 0 0 (Gen: 0) 
    521100  828 134360684 0.00 0.00 0.10 0.19 0 0 (Gen: 0) 
    520812  592 134360528 0.00 0.00 0.10 0.19 0 0 (Gen: 0) 
    520936  1344 134361324 0.00 0.00 0.10 0.19 0 0 (Gen: 0) 
    520788  1480 134361476 0.00 0.00 0.10 0.20 0 0 (Gen: 0) 
134438548  5964 268673908 0.00 0.00 0.19 0.38 0 0 (Gen: 0) 
    586300  3084 268667168 0.00 0.00 0.19 0.38 0 0 (Gen: 0) 
    517840  952 268666340 0.00 0.00 0.19 0.38 0 0 (Gen: 0) 
    520920  544 268666164 0.00 0.00 0.19 0.38 0 0 (Gen: 0) 
    520780  428 268666048 0.00 0.00 0.19 0.38 0 0 (Gen: 0) 
    520820  2908 268668524 0.00 0.00 0.19 0.38 0 0 (Gen: 0) 
    520732  1788 268668636 0.00 0.00 0.19 0.39 0 0 (Gen: 0) 
    521076  564 268668492 0.00 0.00 0.19 0.39 0 0 (Gen: 0) 
    520532  712 268668640 0.00 0.00 0.19 0.39 0 0 (Gen: 0) 
    520764  956 268668884 0.00 0.00 0.19 0.39 0 0 (Gen: 0) 
    520816  420 268668348 0.00 0.00 0.20 0.39 0 0 (Gen: 0) 
    520948  1332 268669260 0.00 0.00 0.20 0.39 0 0 (Gen: 0) 
    520784  616 268668544 0.00 0.00 0.20 0.39 0 0 (Gen: 0) 
    521416  836 268668764 0.00 0.00 0.20 0.39 0 0 (Gen: 0) 
    520488  1240 268669168 0.00 0.00 0.20 0.40 0 0 (Gen: 0) 
    520824  1608 268669536 0.00 0.00 0.20 0.40 0 0 (Gen: 0) 
    520688  1276 268669204 0.00 0.00 0.20 0.40 0 0 (Gen: 0) 
    520252  1332 268669260 0.00 0.00 0.20 0.40 0 0 (Gen: 0) 
    520672  1000 268668928 0.00 0.00 0.20 0.40 0 0 (Gen: 0) 
134553500  5640 402973292 0.00 0.00 0.29 0.58 0 0 (Gen: 0) 
    586776  2644 402966160 0.00 0.00 0.29 0.58 0 0 (Gen: 0) 
    518064  26784 134342772 0.00 0.00 0.29 0.58 0 0 (Gen: 1) 
    520828  3120 134343528 0.00 0.00 0.29 0.59 0 0 (Gen: 0) 
    521108  756 134342668 0.00 0.00 0.30 0.59 0 0 (Gen: 0) 

我々が〜128メガバイトを超える 'ライブバイト' を持っているようです。

+RTS -hyプロファイルは、基本的には、我々は128メガバイトを割り当てる言う:

http://imageshack.us/a/img69/7765/45q8.png

私は単純なプログラムでこの動作を再現しようとしたが、それでもST、ベクターを含むReaderで正確なセットアップを複製すると、同じモナド/プログラムの構造などの単純なテストプログラムはこれを表示しません。私の大きなプログラムを単純化すると、結局無関係なコードを完全に削除したときの動作も停止します。

Qsの:私は本当に20のうちの4倍の周りにこのベクトルを維持

  • アム?
  • 「はい」の場合、実際には+RTS -Hymaximum residencyと主張していますが、この動作を停止するにはどうすればよいですか?
  • もしそうでなければ、なぜHaskellはそれをGC'ingせずにアドレス空間/メモリを使い果たしているのですか?この動作を止めるにはどうすればよいですか?

ありがとう!

+2

使用されるメモリは通常、最大居住度の2倍以上です。割り当ておよび収集パターンによって異なります。したがって、使用されている合計518MBのメモリはそれほど警戒的ではありません。 GHCに、 '$ ./foo + RTS -M256M'など、使用するメモリがあまりにも多いことを伝えて、それを早く収集させるようにしてください。しかし、「runSTの外でそれに保持されている参照も真実でない可能性があります。実際には漏れがあります。そのような場合は、コードを参照する必要があります。 –

+0

@ダニエルフィッシャー518MBは〜4倍です。 1GBベクトルのメモリ不足によるクラッシュは、GHC *がメモリを収集できないことを示していませんか? + RTS -M256Mが「ヒープ排気」で失敗します。ベクトルが作成され、Reader環境内に置かれます。それだけです。他には、ST/Readerから出た後で参照を漏らさないために何ができるかわからない。私が言ったように、私は簡単なプログラムでこの問題を再現することはできません。むしろランダムなようです。 – NBFGRTW

+0

まあ、間違った割り当てパターンが与えられた場合、4倍が起こる可能性があります。メモリ不足のクラッシュは、GHCが現在収集すべきことを知らないことを示しているかもしれませんが、 '-M256M'は' 'heap exhausted ''を引き起こすので、何かが獣への参照を持っているように見えます。 –

答えて

2

これはGHCおよび/またはRTSのバグだと思われます。

まず、実際のスペースリークなどはないと私は確信しています。

理由:

  • ベクトルがどこにも使用されることはありません。読んでいない、書いていない、参照していない。 runSTが完了したら収集する必要があります。 ST計算がただちに出力されて評価するために1つのIntを返す場合でも、メモリの問題は依然として存在します。そのデータへの参照はありません。
  • RTSが提供するすべてのプロファイリングモードは、実際には1つのベクターの価値以上のメモリが割り当てられ/参照されることはありません。すべての統計と美しいグラフはそう言います。

ここで興味深いビットがあります。関数を実行するたびに手動でSystem.Mem.performGCを呼び出してGCを強制すると、問題は完全になくなります。

ランタイムには、GCによって再利用可能なGBのメモリがあり、それ自体の統計情報が誰にも保持されない場合でもあります。メモリプールが不足している場合、ランタイムは収集されず、代わりにOSにより多くのメモリを要求します。そして最終的にそれが失敗しても、ランタイムはまだ収集されません(GBのメモリを再確認します)が、代わりにメモリ不足エラーでプログラムを終了することを選択します。

私はHaskell、GHC、またはGCの専門家ではありません。しかし、これはひどく私に壊れて見えます。これをバグとして報告します。

+0

それを報告する? – jberryman

関連する問題