Mono 当前用 Boehm GC 作为垃圾回收引擎, 不过正在开发一套小型且精准的GC引擎,叫做SGen GC。
Mono用的是Conservative Boehm GC的精准模式,扫描以下这些区域的托管对象的指针:
- 堆,也就是分配托管对象的地方。
- 线程栈和寄存器。
- 静态数据区域。
- 运行时分配的数据结构。
关于Conservative GC(保守GC)的相关文章
- http://hboehm.info/gc/conservative.html
- http://www.iecc.com/gclist/GC-algorithms.html
- http://stackoverflow.com/questions/7629446/conservative-garbage-collector
SGen GC的功能如下:
- 分成两代
- 多线程的
- 主要是精准扫描(栈和寄存器是保守扫描)
- 两个主要的回收器
- Minor,执行Copying
- Major,执行Mark+Sweep
- 回收时暂停程序
SGen GC把内存分成4组管理:
- 幼儿园(Nursery),分配新的小对象的地方。
- 大对象仓库,分配大对象的地方。
- 老代(Old Generation),复制小对象到这。
- 固定块,存放固定分配的对象。
当内存空间用完时就会触发回收操作,回收器会区分用哪个回收器。
共有两个阶段的回收:
- 回收Nursery中的新分配的对象,通常很少能生存下来,大部分都会被回收。
- Nursery中生存下来的并被复制到old Generation内存块的对象。
如果Nursery中内存满了,就会触发Nursery回收,由Minor GC执行Copying,类推如果Old Generation满了,就由Major GC执行回收。
GC复杂的原因在于:
- 必须工作在多线程程序中
- 任何线程都可以触发回收
- 需要知道哪些是固定对象,这些对象不能被移动到Old Generation。
- 大对象移动的代价很大,所以在Major回收中用Mark+Sweep回收
- 有些对象也不能回收,比如内部strings,type handles,也需要用Mark+Sweep处理。
不管是Minor还是Major回收,都要挂起所有线程,保证内存不再改变。