6

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

为此,我正在考虑惰性值:

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

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

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

4

2 回答 2

7

你只需要更多的工具:

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

不会保留对的额外引用,dataString因为您永远不会在构造函数(设置storedData)之外引用它,并且一旦使用它,您存储的引用就会storedData被清空,因此该字符串可以自由地被 GCed。

于 2013-04-27T15:49:53.553 回答
5

它永远不会被垃圾收集的原因是因为 Scala 存储dataString在一个私有字段中,因此惰性函数可以稍后被评估,所以它dataString永远保持不变。如果惰性求值发生在单独的闭包中,这不会有问题,但它只是一个普通的类方法,所以dataString只要类实例存在,它就会被保存。

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

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'
于 2013-04-27T15:55:00.563 回答