9

このSOスレッドseqでは、大きなコレクションでaへの参照を保持すると、コレクション全体がガベージコレクションされるのを防ぐことができることを学びました。

まず、そのスレッドは2009年のものです。これは「最新の」Clojure(v1.4.0またはv1.5.0)でも当てはまりますか?

第二に、この問題は怠惰なシーケンスにも当てはまりますか?たとえば(def s (drop 999 (seq (range 1000))))、ガベージコレクターが999シーケンスの最初の要素をリタイアできるようにしますか?

最後に、大規模なコレクションでこの問題を回避する良い方法はありますか?つまり、たとえば1,000万個の要素のベクトルがある場合、消費された部分をガベージコレクションできるようにベクトルを消費できますか?1000万個の要素を持つハッシュマップがある場合はどうなりますか?

私が尋ねる理由は、私がかなり大きなデータセットを操作しているためです。オブジェクトへの参照を保持しないように注意する必要があります。これにより、不要なオブジェクトをガベージコレクションできるようになります。そのまま、java.lang.OutOfMemoryError: GC overhead limit exceededエラーが発生する場合があります。

4

2 に答える 2

7

シーケンスの「ヘッドを保持」すると、Clojure はすべてをメモリに保持するよう強制されることが常にあります。選択の余地はありません。あなたはまだそれへの参照を保持しています。

ただし、「GC オーバーヘッド制限に達しました」は、メモリ不足エラーと同じではありません。オブジェクトを非常に高速に作成および破棄する架空のワークロードを実行している可能性が高いため、GC をだましてそれを認識させている可能性があります。過負荷です。

見る:

処理中のアイテムに実際の作業負荷をかけると、このエラーが発生しなくなることがわかると思います。この場合、使用可能なメモリよりも大きいレイジー シーケンスを簡単に処理できます。

ただし、ベクトルやハッシュマップなどの具体的なコレクションは別の問題です。これらは遅延ではないため、常に完全にメモリに保持する必要があります。メモリより大きいデータセットがある場合、次のオプションがあります。

  • 怠惰なシーケンスを使用し、頭につかまらないでください
  • 遅延読み込みをサポートする特殊なコレクションを使用します (Datomic はこのような構造を使用していると思います)
  • データをイベント ストリームとして扱う (Storm などを使用)
  • カスタム コードを記述して、データをチャンクに分割し、一度に 1 つずつ処理します。
于 2013-02-22T00:05:04.607 に答える
0

バインディングでシーケンスのヘッドを保持している場合は正しく、gc できません (これは Clojure のすべてのバージョンで行われます)。大量の結果を処理している場合、なぜ頭をつかむ必要があるのでしょうか?

それを回避する方法については、はい!lazy-seq 実装は、既に「処理」されていて、バインディング内から直接参照されていないパーツを gc できます。シーケンスの先頭を保持していないことを確認してください。

于 2013-02-21T18:04:11.007 に答える