如何有效地引用计数cons细胞(检测周期)?

时间:2013-10-02 16:56:58

标签: c optimization lisp automatic-ref-counting cons

我需要制作某种liblisp(在C11中),它需要处理基本函数,就像libobjc对Objective-C语言所做的那样。

修改

我正在将问题重写为不太通用的问题。

我得到了这样的实现:

typedef struct cons {
  void *car, *cdr;
} *cons_t;

cons_t cons_init(void *, void *);
void *cons_get_car(cons_t);
void *cons_get_cdr(cons_t);
void cons_set_car(cons_t, void *);
void cons_set_cdr(cons_t, void *);
void cons_free(cons_t);
bool cons_is_managed(cons_t);

所以我可以制作一个cons单元格(它使用带引用计数对象的内存池)。我还可以使用cons_is_managed来检查cons单元是否在内存池中(这样你就可以使用外部定义的单元格,而不是用cons_init创建的单元格(如静态数据)。

如何在此处有效地实现自动引用计数,如果有人调用cons_set_carcons_set_cdr,如果void *参数是托管增量单元,它会增加引用计数?< / p>

后宫和乌龟的问题在这里没有用,因为每个单元都有两种可能的方法(如果汽车或cdr是conses,它可能无处可去),它们可以是列表,树或图形。 / p>

我应该注册在cons_set_car / cons_set_cdr上使用的外部(非托管)conses,以便找到涉及它们的循环,但我仍然不确定如何执行此操作有效地

由于这是一个更受控制的上下文然后是图形中的一般循环(节点上最多两个顶点),我是否有机会在线性时间内完成此操作并避免垃圾收集(这将是我的计划B)?

主要问题是这是任何函数式语言的核心,因此这些函数将被称为很多次(如obj_msgSend),它们是 < / strong>瓶颈。

感谢。


在另一种方法上,简化问题:如何在基于引用计数的语言上实现cons单元格,如Objective-C + ARC或Vala?

1 个答案:

答案 0 :(得分:1)

我假设您要实现的引用计数的主要目标是高效的垃圾收集(即使您说&#34;避免垃圾收集&#34;,很明显,您的目标是实现自动内存管理)。

首先,我建议您考虑是否转而使用某种tracing garbage collection,例如大多数现代Lisp实现都使用。它与引用计数垃圾收集之间的基本区别是对内存的正与负关系:使用引用计数,假定分配的元素是有效的,直到另外证明(通常通过图遍历算法)。通过跟踪,除非另有证明(通过来自根对象的根集合,例如REPL接口),否则分配的元素将被假定为垃圾。

是的,当标记和扫描算法运行时,您可以偶尔获得显着的性能损失,但取决于您的库的目标可能是值得的。同样,如果您仔细管理线程,则可以让一个核心处理垃圾收集,而另一个继续执行。最有效的是,有混合策略,例如执行&#34;廉价&#34;引用计数不能处理循环以处理高频容易的情况,然后使用跟踪方法收集累积的循环垃圾。

至于如何有效地做...如果你想做引用计数,你需要每个缺点存储一个数字。为什么不将它存储在结构中呢?

typedef struct cons {
   void *car, *cdr;
   size_t reference_count;
} *cons_t;

如果采用混合策略,则可以在O(n)时间内处理地图,缩减和递归函数中的列表处理等高频操作,其中n是要进行垃圾回收的元素数。