在C ++ 0x中压缩垃圾回收器实现
我在C ++ 0x中为自己的个人使用实现了一个压缩垃圾收集器,并且我有一个问题。 很明显,收集器的机制取决于移动的对象,我一直想知道如何通过指向它的智能指针类型来实现这一点。 我一直在考虑指针类型本身的指针指针,或者,收集器维护一个指向每个对象的指针列表,以便它们可以被修改,在访问时不需要双重de-ref指针但在收集和额外的内存开销期间增加额外的开销。 去这里最好的方式是什么?
编辑:我主要关心的是快速分配和访问。 我并不关心特别高效的收集或其他维护,因为这不是真正用于GC的目的。
这是一个非常简单的问题,所以这里是一个直截了当的答案:
在分配和访问(避免双重de-refs)时, mark-and-compact
Mark-and-sweep
(偶尔mark-and-compact
以避免堆碎片)是最快的。 这也很容易实现。 既然你不担心收藏性能的影响(标记和扫描倾向于以非确定性的方式冻结这个过程),这应该是一条路。
实施细节见于:
关于将额外的GC移植到C ++没有什么简单的,更不用说压缩算法了。 目前还不清楚你想要做什么以及它如何与其余的C ++代码进行交互。
我实际上已经用C ++编写了一个gc,它可以与现有的C ++代码一起工作,并且在一个阶段有一个压缩器(尽管我放弃了它,因为它太慢了)。 但是有许多讨厌的语义问题。 我几周前才向Bjarne提到C ++缺乏必要的操作员来正确地执行它,并且情况是它不太可能存在,因为它具有有限的实用性。
你真正需要的是一个“re-addres-me”操作符。 会发生什么是你实际上并没有移动物体。 您只需使用mmap来更改对象地址。 这要快得多,实际上,它使用VM功能来提供句柄。
如果没有这个功能,你必须有一种方法来执行一个对象的重叠移动,这是你不能用C ++高效执行的:你必须首先移动到临时对象。 在C中,它更容易,你可以使用memmove
。 在某个阶段,所有进入或移入被移动对象的指针都必须进行调整。
使用句柄并不能解决这个问题,它只是将问题从任意大小的对象减少到常量大小的对象:这些对于数组来说更容易管理,但存在同样的问题:您必须管理存储。 如果随机删除阵列中的大量句柄,则仍然存在碎片问题。
所以不要打扰手柄,他们不工作。
这就是我在菲利克斯所做的:你称之为new(shape, collector) T(args)
。 这里的shape
是类型的描述符,包括包含(GC)指针的偏移量列表,以及定义对象的例程地址(默认情况下它调用析构函数)。
它还包含一个标志说,如果该对象可以与移动memmove
。 如果对象很大或不可移动,则由malloc
分配。 如果物体很小且具有移动性,则将其分配到竞技场中,前提是场地中有空间。
通过移动其中的所有对象并使用形状信息来全局调整所有指向这些对象的指针或通过这些对象进行调整。 压缩可以逐步完成。
C ++程序员的缺点是需要构造一个正确的shape
对象来传递。 这并不妨碍我,因为我正在实现一种可以自动生成形状信息的语言。
现在:关键是:要做压实,你必须使用精确的收集器。 压实不能与保守的收藏家合作。 这个非常重要。 如果你看到一个看起来像指针的值,但碰巧是一个整数,那么允许一些泄漏是很好的:某些对象不会被收集,但这通常不是什么大问题。 但是为了压缩,你必须调整指针,但是你最好不要改变这个整数:所以你必须知道什么时候是指针,所以你的收集器必须是精确的:形状必须是已知的。
在Ocaml中,这相对简单:所有内容都是指针或整数,低位用于运行时告诉。 指向的对象有一个告诉类型的代码,并且只有几种类型:标量(不扫描它)或聚合(扫描它,它只包含整数或指针)。
幼儿园的一代会给你最好的配置性能,因为它只是一个指针凹凸。
您可以通过使用诸如影子堆栈之类的技术来实现指针更新,而不使用双重间接,但如果您手动编写此C ++代码,这将会很慢并且非常容易出错。
链接地址: http://www.djcxy.com/p/79095.html上一篇: Compacting garbage collector implementation in C++0x
下一篇: How does Object.GetHashCode work when the GC moves an object?