5

私は非常に多くの数のリストを持っており、それらは多くの数学操作を受けます。私は最終結果だけを気にします。この動作をシミュレートするには、以下のサンプルコードを参照してください。

object X { 
def main(args:Array[String]) = {
    val N = 10000000
    val x = List(1 to N).flatten
    println(x.slice(0,10))
    Thread.sleep( 5000)
    val y = x.map(_*5)
    println(y.slice(0,10))
    Thread.sleep( 5000)
    val z = y.map( _+4)
    println(z.slice(0,10))
    Thread.sleep( 5000)
}
     }

したがって、xは非常に大きなリストです。結果zだけが気になります。zを取得するには、最初にxを数学的に操作してyを取得する必要があります。次に、yを操作してzを取得します。(操作が非常に複雑なため、1つのステップでxからzに移動することはできません。これは単なる例です。)

したがって、この例を実行すると、おそらくx、y、zがすべてスコープ内にあり、それらがすべてメモリを占有しているために、メモリが不足しています。

だから私は次のことを試みます:

def main(args:Array[String]) = {
    val N = 10000000
    val z = {
            val y = {
                val x = List(1 to N).flatten
                println(x.slice(0,10))
                Thread.sleep( 5000)
                x

            }.map(_*5)

            println(y.slice(0,10))
            Thread.sleep( 5000)
            y

    }.map( _+4)
    println(z.slice(0,10))
    Thread.sleep(5000)
}

したがって、zのみがスコープに含まれます。したがって、おそらくxとyが作成され、スコープ外になるとガベージコレクションが行われます。しかし、これは何が起こるかではありません。代わりに、私は再びメモリを使い果たしました!

(注:私はjava -Xincgcを使用していますが、役に立ちません)

質問:1つの大きなリストに十分なメモリがある場合、valのみを使用して(つまり、可変変数やListBuffersを使用せずに)、おそらくスコープを使用してgcを強制することでそれを操作できますか?もしそうなら、どのように?ありがとう

4

3 に答える 3

8

このようなことを試しましたか?

val N = 10000000
val x = List(1 to N).flatten.view // get a view
val y = x.map(_ * 5)
val z = y.map(_ + 4)
println(z.force.slice(0, 10))

yとの中間完全構造の作成を回避するのに役立つはずzです。

于 2011-11-25T19:47:59.560 に答える
3

の使用を見てくださいview。コレクションを取得して遅延ロードし、必要な場合にのみ値を計算します。中間コレクションは形成されません。

scala> (1 to 5000000).map(i => {i*i}).map(i=> {i*2}) .toList
java.lang.OutOfMemoryError: Java heap space
        at java.lang.Integer.valueOf(Integer.java:625)
        at scala.runtime.BoxesRunTime.boxToInteger(Unknown Source)
        at scala.collection.immutable.Range.foreach(Range.scala:75)
        at scala.collection.TraversableLike$class.map(TraversableLike.scala:194)
        at scala.collection.immutable.Range.map(Range.scala:43)
        at .<init>(<console>:8)
        at .<clinit>(<console>)
        at .<init>(<console>:11)
        at .<clinit>(<console>)
        at $print(<console>)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:704)
        at scala.tools.nsc.interpreter.IMain$Request$$anonfun$14.apply(IMain.scala:920)
        at scala.tools.nsc.interpreter.Line$$anonfun$1.apply$mcV$sp(Line.scala:43)
        at scala.tools.nsc.io.package$$anon$2.run(package.scala:25)
        at java.lang.Thread.run(Thread.java:662)
scala> (1 to 5000000).view.map(i => {i*i}).view.map(i=> {i*2}) .toList
res10: List[Int] = List(2, 8, 18, 32, 50, 72, ...
于 2011-11-25T19:55:07.227 に答える
0

安価な答えですが、より多くのメモリを使用してjvmを起動してみましたか?

例えば

$ java -X...-Xmxは最大Javaヒープサイズを設定します

また、移行中にメモリ内の2つのリストに同時に巻き込まれ、両方が参照されているように見えるため、GCはおそらく役に立ちません。

于 2011-11-25T19:40:17.557 に答える