如果我持有对持久集合的一部分的引用,整个集合是否可以被垃圾收集?我能正确理解吗?
函数gctest只是测试集合的行为.
(defn gctest
"A shot about testing the gc-ability of persistent thingies."
[n]
(take 5 (drop 100 (vec (range n)))))
main=> (def a (gctest 1e7))
main=> (def b (gctest 1e7))
main=> (def c (gctest 1e7))
main=> (def d (gctest 1e7))
main=> (def e (gctest 1e7))
main=> (def f (gctest 1e7))
main=> (def g (gctest 1e7))
OutOfMemoryError GC overhead limit exceeded clojure.lang.ArrayChunk.dropFirst (ArrayChunk.java:54)
Run Code Online (Sandbox Code Playgroud)
我已经听说过头部保留,但这看起来有点笼统或者不是吗?
我想要了解的是如何使用大变化的收藏.我希望收藏品的大部分内容会随着时间的推移而发生变化,原则上大部分可以被垃圾收集,但不是全部.
有没有一种标准的方法来应对这种情况?
标准GC规则仍然存在:只要您保留对集合的一部分的引用,您的引用可访问的所有对象都将保留在内存中.因此,只有从您的参考文献中可以访问的集合部分将被保留,其余部分将被收集.特别是,如果您引用100个元素列表的最后50个元素,将收集前50个元素,其余元素将保留在内存中.
但是,在您的情况下,将保留从100开始的每个集合的所有元素.而它的原因是懒惰的评价.函数take产生(在您的情况下)5个元素的惰性序列.懒惰的序列对象本身不是真正的序列,而是它是特殊的生成器对象(虽然它不是Clojure的,而是Python的术语).当你需要延迟序列的元素时,生成器对象会生成并返回它.但是如果你不要求元素,生成器只会保留对生成元素所需的所有对象的引用.
在您的例子中,你创建的大载体,并要求从它5个元素,然后将结果变量a,b,c,等的Clojure使得大载体和发电机的对象,指向100元.对集合本身的引用将丢失,但对生成器对象的引用将保存在顶层.您永远不会评估生成器对象,因此永远不会生成真正的5元素序 REPL指VARS a,b,c等等,这些VARS指发电机对象,以及对象发生器指他们需要产生真实5个元件序列的集合.因此,所有集合中的所有元素(除了可能是前100个)都必须留在内存中.
另一方面,如果您评估生成器对象,它们将生成真正的5个元素序列,并忘记对其余集合的引用.试试这个:
user> (def a (gctest 1e7))
#'user/a
user> (println a)
(100 101 102 103 104)
nil
user> (def b (gctest 1e7))
#'user/b
user> (println b)
(100 101 102 103 104)
nil
user> (def c (gctest 1e7))
#'user/c
user> (println c)
(100 101 102 103 104)
nil
user> (def d (gctest 1e7))
#'user/d
user> (println d)
(100 101 102 103 104)
nil
user> (def e (gctest 1e7))
#'user/e
user> (println e)
(100 101 102 103 104)
nil
user> (def f (gctest 1e7))
#'user/f
user> (println f)
(100 101 102 103 104)
nil
user> (def g (gctest 1e7))
#'user/g
user> (println g)
(100 101 102 103 104)
nil
user> (def h (gctest 1e7))
#'user/h
user> (println h)
(100 101 102 103 104)
nil
user> (def i (gctest 1e7))
#'user/i
user> (println i)
(100 101 102 103 104)
nil
Run Code Online (Sandbox Code Playgroud)
没有OutOfMemory!瓦尔a,b,c等现在存储真正的清单5个元素,因而有大集合没有更多的引用,因此它们可以被回收.
| 归档时间: |
|
| 查看次数: |
1250 次 |
| 最近记录: |