1

現在、JRPG スタイルのゲームを作成しており、YAML ファイルでアイテム/敵などを定義しています。それらを実行時にロードするのではなく (これは Scala、特に Android では面倒です)、それらを遅延値として Scala オブジェクトにプリコンパイルすることにしました。

私の唯一の懸念は、最終的にこれらの値がアクセスされると、オブジェクトが実際に必要以上のメモリを消費し始めることです。

Scala オブジェクトを再初期化する方法や、遅延値をクリアしてデフォルト状態に戻す方法はありますか? または、ここでやろうとしていることを達成するためのより良い方法はありますか?

4

5 に答える 5

8

これには、ソフト(弱ではない)参照が非常に便利だと思います。弱い参照は、不要な GC ごとに消費されます。これは、繰り返しアクセスされると、多くの労力を浪費する可能性があります。ソフト参照は、メモリ プレッシャーがある場合にのみ使用されます (正式にはすべての GC である可能性がありますが、少なくとも JVM は少し裁量を行使できます)。とにかく、Scala で使用する場合、これは非常に便利です。

class Soft[T,U](t: T)(gen: T => U) {
  private[this] var cache = new java.lang.ref.SoftReference(gen(t))
  def apply(): U = {
    var u = cache.get()
    if (u==null) {
      u = gen(t)
      cache = new java.lang.ref.SoftReference(u)
    }
    u
  }
}
object Soft {
  def apply[T,U](t: T)(gen: T => U) = new Soft(t)(gen)
}

これで、適切な量のものを でラップし、必要なときにデータを取得するためにSoft使用します。()

val soft = Soft(10)(n => Array.tabulate(n)(i => i*i*i))
soft()(3)   // 27

ソフト参照を取得するには、完全に無視できないほどのペナルティがあります (通常、オブジェクトの作成数に相当します)。

val arr = soft()
// Intensive operations with arr
于 2013-03-16T15:15:20.697 に答える
2

そのようなメカニズムはありません。alazy valがアクセスされ、そのイニシャライザが評価されると、結果の値は、他のインスタンスと同様にその一部であるインスタンスのフィールドに保持され、そのインスタンス自体がガベージになるだけで、その「怠惰な」値への参照を放棄し、(おそらく) 同様に再利用できるようにします。当然、それへの他の参照がある場合、それらはその再利用を妨げます。

于 2013-03-16T04:08:53.617 に答える
1

組み込みのメカニズムはないと思いますので、自分で実装する必要があります。最も簡単な解決策は、特定の時間が経過した後に有効期限が切れる何らかの形式のキャッシュを用意することです。たとえば、有効期限が切れるキーを使用するJavaの時間ベースのマップ/キャッシュで説明されています。

于 2013-03-16T06:19:06.093 に答える
1

持っているかどうかによって異なります-それらを「弱い値」と呼びましょう-異なるタイプまたは1つのタイプの弱い値ですが、多くのオブジェクトが関係しています。後者の場合は、マップ/キャッシュを使用した Rogach によるソリューションを使用します。

ただし、最初の異なるクラスまたはいくつかの大きなオブジェクトがある場合、1 つのアプローチは確実にWeakReferenceを使用することです。

これは私が思いついた解決策です - おそらく将来的にはマクロでこれを行うことができます:

object UseWeakRef extends App {

  import scala.ref.WeakReference

  class WeakRefCreator[T <: AnyRef] {
    private var weakRef: WeakReference[T] = WeakReference(null.asInstanceOf[T])
    def apply(creator: => T): T = weakRef.get match {
      case None =>
        val newVal: T = creator
        weakRef = WeakReference(newVal); newVal
      case Some(value) => value
    }
  }

  private val expensiveRef = new WeakRefCreator[String]
  def expensiveVal = expensiveRef {
    println("creating expensive object")
    "This is expensive"
  }

  println(expensiveVal)
  println(expensiveVal)
}

出力は次のとおりです。

creating expensive object
This is expensive
This is expensive
于 2013-03-16T06:29:59.540 に答える