在计算延迟值后,垃圾收集对象

时间:2013-04-27 15:36:11

标签: scala garbage-collection lazy-evaluation

在我目前的项目中,我正在处理大量数据,并且数据处理应该是内存效率和计算性能。 每个项目都有一些可以非常快速地读取的元数据,并且几乎总是很有趣。除此之外,每个项目都具有相对较少读取的实际数据,但阅读尤其是解析非常耗时。因此,它接缝很自然,只有在实际请求时才能解析数据。

为此我想到了懒惰的价值观:

class Item(metaData: MetaData, dataString: String) {
    lazy val data = parse(dataString)
}

现在只有在实际请求时才会解析数据。问题是,dataString和解析后的数据保存在内存中。据我所知,只要“数据”被调用(或者存在?)就不能再访问“dataString”了,因此它可以被垃圾收集。不幸的是,这种接缝不会发生。

有没有办法以不同的方式解决问题或者给垃圾收集器提示垃圾收集dataString?

2 个答案:

答案 0 :(得分:7)

您只需要更多工具:

class Item(dataString: String) {
  private var storedData = dataString
  lazy val data = {
    val temp = parse(storedData)
    storedData = null
    temp
  }
}

未保留对dataString的额外引用,因为您从未在构造函数之外引用它(设置storedData),并且您在storedData中存储的引用将被清除一次你使用它,所以字符串可以自由地进行GCed。

答案 1 :(得分:5)

它永远不会被垃圾收集的原因是因为Scala将dataString存储在私有字段中,因此稍后可以评估延迟函数,因此它永远保留在dataString上。如果延迟评估发生在一个单独的闭包中,这不会是一个问题,但它只是一个普通的类方法,所以只要类实例是dataString就行。{/ p>

您可以通过编译和反汇编课程来看到这一点。

class Item(dataString: String) {
    lazy val data = parse(dataString)


    def parse(s: String) = s.reverse

}

正如反汇编所示,创建了一个存储在构造函数中的最终私有字段dataString。延迟评估在方法data$lzycompute中进行,方法取值dataString,对其执行计算,并将结果存储在data字段中。但dataString仍然保持其原始价值。

它还定义了一个字段bitmap$0来跟踪是否已经评估了惰性函数,还有一个名为data的包装器访问器成员,如果需要调用该函数然后返回该字段data

.version 50 0
.class super public Item
.super java/lang/Object
.runtimevisible annotation Lscala/reflect/ScalaSignature;
    bytes =  string [_7]
.end annotation
.attribute ScalaSig '\x05\x00\x00'

.field final private dataString Ljava/lang/String;
.field private data Ljava/lang/String;
.field volatile private bitmap$0 Z

.method private data$lzycompute : ()Ljava/lang/String;
    .limit stack 3
    .limit locals 2
    .catch [0] from L4 to L34 using L46
    aload_0
    dup
    astore_1
    monitorenter
L4:
    aload_0
    getfield Item bitmap$0 Z
    ifne L28
    aload_0
    aload_0
    aload_0
    getfield Item dataString Ljava/lang/String;
    invokevirtual Item parse (Ljava/lang/String;)Ljava/lang/String;
    putfield Item data Ljava/lang/String;
    aload_0
    iconst_1
    putfield Item bitmap$0 Z
L28:
.stack append
    locals Object Item
.end stack
    getstatic scala/runtime/BoxedUnit UNIT Lscala/runtime/BoxedUnit;
    pop
    aload_1
    monitorexit
L34:
    aload_0
    aconst_null
    pop
    aconst_null
    putfield Item dataString Ljava/lang/String;
    aload_0
    getfield Item data Ljava/lang/String;
    areturn
L46:
.stack same_locals_1_stack_item
    stack Object java/lang/Throwable
.end stack
    aload_1
    monitorexit
    athrow
.end method

.method public data : ()Ljava/lang/String;
    .limit stack 1
    .limit locals 1
    aload_0
    getfield Item bitmap$0 Z
    ifeq L14
    aload_0
    getfield Item data Ljava/lang/String;
    goto L18
L14:
.stack same
    aload_0
    invokespecial Item data$lzycompute ()Ljava/lang/String;
L18:
.stack same_locals_1_stack_item
    stack Object java/lang/String
.end stack
    areturn
.end method

.method public parse : (Ljava/lang/String;)Ljava/lang/String;
    .limit stack 4
    .limit locals 2
    new scala/collection/immutable/StringOps
    dup
    getstatic scala/Predef$ MODULE$ Lscala/Predef$;
    aload_1
    invokevirtual scala/Predef$ augmentString (Ljava/lang/String;)Ljava/lang/String;
    invokespecial scala/collection/immutable/StringOps <init> (Ljava/lang/String;)V
    invokeinterface scala/collection/IndexedSeqOptimized reverse ()Ljava/lang/Object; 1
    checkcast java/lang/String
    areturn
.end method

.method public <init> : (Ljava/lang/String;)V
    .limit stack 2
    .limit locals 2
    aload_0
    aload_1
    putfield Item dataString Ljava/lang/String;
    aload_0
    invokespecial java/lang/Object <init> ()V
    return
.end method

.const [_7] = Utf8 '\x06\x01)2A!\x01\x02\x01\x0b\t!\x11\n^3n\x15\x05\x19\x11a\x02\x1ff[B$\x18PP\x02\x01\'\t\x01a\x01\x05\x02\x08\x195\t\x01B\x03\x02\n\x15\x05!A.\x198h\x15\x05Y\x11\x01\x026bm\x06L!!\x04\x05\x03\r=\x13\'.Z2u\x11!y\x01A!A!\x02\x13\x01\x12A\x033bi\x06\x1cFO]5oOB\x11\x11c\x06\x08\x03%Ui\x11a\x05\x06\x02)\x05)1oY1mC&\x11acE\x01\x07!J,G-\x1a4\n\x05aI"AB*ue&twM\x03\x02\x17\'!)1\x04\x01C\x019\x051A(\x1b8jiz""!H\x10\x11\x05y\x01Q"\x01\x02\t\x0b=Q\x02\x19\x01\t\t\x11\x05\x02\x01R1A\x05\x02\t\nA\x01Z1uCV\t\x01\x03\x03\x05%\x01!\x05\t\x15)\x03\x11\x03\x15!\x17\r^1!\x11\x151\x03\x01"\x01(\x03\x15\x01\x18M]:f)\t\x01\x02\x06C\x03*K\x01\x07\x01#A\x01t\x01'