【发布时间】:2014-08-06 06:53:58
【问题描述】:
Chapter 21, Real World OCaml,上面写着:
次要堆是保存大部分短期值的地方。它 由一块连续的虚拟内存组成,其中包含一个 OCaml 块的序列。如果有空间,分配一个新块是 一个快速、恒定时间的操作,只需要几个 CPU 说明。
为了对次堆进行垃圾收集,OCaml 使用复制收集将次堆中的所有活动块移动到主堆。这需要 工作与次堆中的活动块数成正比, 根据世代假设,这通常很小。这 次要收集停止了世界(它停止了应用程序) 当它运行时,这就是为什么它如此重要以使其快速完成 让应用程序以最小的中断恢复运行。
我明白正如它所说的那样,在小堆中,实时内存进入主堆。
但是,gc 如何决定小堆中的实时内存?
主堆的标记和清除过程是否相同?
基本上,在 major 堆的 gc 期间,它会在堆栈中启动一些根,并且任何可以到达的东西都是实时的。
如果minor的gc也是这种情况,那么OCaml如何快速知道哪些根导致了minor heap memory,或者快速知道哪些root导致了major memory?
我的困惑实际上是如果OCaml 对minor 和major 做相同的gc 操作,那么OCaml 怎么区分?如果都是从栈开始,GC怎么能只在minor上收集,不涉及major呢?
编辑
假设次要堆大小只有 4KB。这是一些代码:
let f =
let a1 = Array.make (4 * 1024) 1 in
let a2 = Array.make (4 * 1024) 2 in
let a3 = Array.make (4 * 1024) 3 in
...
在上面的代码中
-
a1的地址将被放入堆栈,真正的数组将在小堆中。堆栈看起来像[a1]。 -
a2正在创建中。它发现次要堆已满,因此将执行次要 gc。 gc 查看堆栈,因此跟随 a1 并确定 a1 处于活动状态,然后a1's array将被复制到主堆,并且 a1 的指针更改为主堆中的新地址?堆栈现在看起来像[a2;a1]。 -
a3正在创建中。就像2一样,它必须做一个小gc。 gc 会通过 a2 和 a1 吗?尤其是 a1,即使 a1 是大调?
【问题讨论】:
-
你应该阅读 Wilson 的 www3.nd.edu/~dthain/courses/cse40243/spring2006/gc-survey.pdf 。从 StackOverflow 问题中弄清楚是没有意义的。