Mono 3现在是默认 GC是SGen 垃圾回收器,垃圾回收器几个性能和扩展性方面的改进,以更好地利用多核处理器硬件。SGen 已移植到 Windows 和 MIPS。
mono 最开始使用的是 Boehm-Demers-Wiser Conservative Garbage Collector ,mono 3.0之前的版本作为默认的垃圾收集器也是这个,Boehm垃圾收集器的主要问题在于无法精确读取寄存器与栈帧。因为无法确定给定值到底是指针还是标量,因此它总是假设给定值是指针,并且将相关联的对象标记为存活状态。这么做不仅会错误导致大块内存无法分配,同时还使得压缩可用空间这项工作变得异常艰难。
后来mono有了自己的 Simple Generational GC , 就是分代式垃圾回收器Sgen,取代了Mono中传统的 Boehm垃圾回收器。文档地址:http://www.mono-project.com/Compacting_GC,它使用精确的分代式(generational)垃圾收集器,类似于.NET版本的CLR。SGen垃圾收集器使用两生代而非.NET中的三个,但像.NET一样对于大对象使用独立的堆。
- 分为两代,之前使用 conservative gc..可见其文档的描述。是一种较为落后的实现,没有分代,.NET 的CLR是三代的
- 大对象特殊处理,默认大于64KB作为大对象,.NET的大对象是20KB以上,被分配到一个特殊的大对象堆中。该堆中的对象像其它小对象一样可以被finalized和释放。
- 小对象采用get_internal_mem/free_internal_mem 进行内存分配处理,大对象使用OS的malloc/free
- major collection 的时候采用 mark/sweep
- 收集进行时是 “stop the world”
- 保守扫描对象
- 老一代指向新一代的情况只有下面两种,所以都进行了跟踪:
- 程序执行中,一个字段进行了赋值
- 在复制(代移动)过程中,这个对象指向了一个新一代中的对象
Mono 3.2进一步提升了SGen GC,特别是针对下面的场景——
- 流行对象负载,老一代对象非常欢迎的一些固定新生对象会导致创建很多记忆的集合。为了避免这种情况的发生,流行对象会被作为永恒对象直到下一次主收集。
- 大规模线程栈负载,这种情况下需要合理地扫描大量大堆栈线程。这在以前通常会把大量压力放到规划阶段,因为它会产生非常大的固定队列。为了避免这种情况,SGen现在会在固定队列上使用哈希过滤,这大大降低了它们的平均大小,并且它会固定主要块而不是个别对象。
Mono 3.0添加了异步支持、改进的SGen垃圾收集器及其他特性
SGen – Concurrency and Evacuation