5

valブロック内で一度だけ使用される sへの参照を削除することにより、scala コンパイラはメモリ使用量を最適化しますか?

巨大なデータを集約して保持しているオブジェクトを想像してみてください。データまたはその派生物を複製すると、JVM/マシンのメモリの最大量をスクラッチする可能性があるサイズに達します。

最小限のコード例ですが、より長い一連のデータ変換を想像してください。

val huge: HugeObjectType
val derivative1 = huge.map(_.x)
val derivative2 = derivative1.groupBy(....)

コンパイラは、たとえば、計算huge後にガベージ コレクションの対象としてマークしたままにしますか? derivative1それとも、ラッピングブロックが終了するまで生き続けますか?

不変性は理論的には素晴らしいものです。個人的には中毒性があると思います。しかし、現在のオペレーティング システムでアイテムごとにストリーム処理できないビッグ データ オブジェクトに適合させるためには、JVM でのビッグ データ アプリケーションの場合、合理的なメモリ使用率と本質的にインピーダンスのミスマッチであると主張します。コンパイラがこのようなことを最適化しない限り、そうではありません..

4

2 に答える 2

8

まず第一に、未使用メモリの実際の解放は、JVM GC が必要と判断したときに行われます。したがって、これについて scalac ができることは何もありません。

scalacができる唯一のことは、参照がスコープ外になったときだけでなく、使用されなくなったらすぐに参照を null に設定することです。

基本的

val huge: HugeObjectType
val derivative1 = huge.map(_.x)
huge = null // inserted by scalac
val derivative2 = derivative1.groupBy(....)
derivative1 = null // inserted by scalac

scala-internals のこのスレッドによると、現在これを行っておら、最新のホットスポット JVM もサルベージを提供していません。scalac ハッカー Grzegorz Kossakowski の投稿とそのスレッドの残りを参照してください。

JVM JIT コンパイラーによって最適化されているメソッドの場合、JIT コンパイラーはできるだけ早く参照をヌルにします。ただし、一度だけ実行されるメイン メソッドの場合、JVM はそれを完全に最適化しようとはしません。

上記のリンクのスレッドには、このトピックとすべてのトレードオフに関するかなり詳細な議論が含まれています。

Apache Spark などの一般的なビッグ データ コンピューティング フレームワークでは、操作する値はデータへの直接参照ではないことに注意してください。したがって、これらのフレームワークでは、通常、参照の有効期間は問題になりません。

上記の例では、すべての中間値が 1 回だけ使用されます。したがって、簡単な解決策は、すべての中間結果を定義として定義することです。

def huge: HugeObjectType
def derivative1 = huge.map(_.x)
def derivative2 = derivative1.groupBy(....)
val result = derivative2.<some other transform>

別の非常に強力なアプローチは、反復子を使用することです! mapイテレータのような連鎖関数はfilterアイテムごとにそれらを処理するため、中間コレクションが具体化されることはありません..これはシナリオに非常によく適合します! これは次のような関数には役立ちませんgroupByが、以前の関数や同様の関数のメモリ割り当てを大幅に削減する可能性があります。上記のサイモン・シェーファーのクレジット。

于 2015-11-22T12:05:19.420 に答える
2

derivative1範囲外になると、ガベージコレクションが行われます(そして、それへの他の参照はありません)。できるだけ早くそれが確実に行われるようにするには、次のようにします。

val huge: HugeObjectType
val derivative2 = {
    val derivative1 = huge.map(_.x)
    derivative1.groupBy(....)
}

これはコードの可読性の観点からも優れています。 が存在する唯一の理由はであり、閉じ括弧の後には使用されないことが明らかだからです。derivative1derivative2

于 2015-11-22T16:54:46.217 に答える