心寄笔端 附庸风雅

甘草的技术博客

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

本来应该先写最具有代表性的Java的GC的,但是目前我正在看Python的源代码,而且Python和Java的GC,有着很多相似点,所以就用这个顺序了,Python的GC章节,我打算更多地着眼于实现和我的疑问,Java的GC章节,更多放在使用上。

GC in Python

Python是走多种GC技术路线相结合的路线的,我以为有可取之处。首先Python采用了原始的Ref Counting技术【1】,而对于引用计数解决不了的循环引用,Python也采用了Mark-Sweeping进行GC。这样似乎有两个好处,大量的内存回收,分摊给了引用计数上,减轻了Mark过程的负担,不会造成程序的停顿,而又可以真正的消除循环引用等造成的真实的内存泄露。

从对象创建的过程来看,Python有如下几个关键的C实现函数和结构:

_PyObject_GC_New将会调用_PyObject_GC_Malloc,其中前者的返回值,关注的是对象本身,而后者关注的是内存,实际上,在一块刚刚分配的内存上,对象和它锁在的内存有着如下的关系:

/* Get an object's GC head */
#define AS_GC(o) ((PyGC_Head *)(o)-1)
/* Get the object given the GC head */
#define FROM_GC(g) ((PyObject *)(((PyGC_Head *)g)+1))

 也就是说,在一个Python对象所在的内存上,它的前端还有一部分用于GC的内存数据,而这个结构就是

 

typedef union _gc_head {
    
struct {
        union _gc_head 
*gc_next;
        union _gc_head 
*gc_prev;
        Py_ssize_t gc_refs;
    } gc;
    
long double dummy;  /* force worst-case alignment */
} PyGC_Head;

其实,我本人对这个结构稍有失望,因为要回收一块内存,所占用的资源实在是太多了。可能是我太小家子气了,我觉得8个字节也许刚刚好。【2】老实说,在我心中,已有一个初步的想法,一个对象的管理内存,完全仅仅需要8个字节足够了,而且整个GC的过程,不需要拷贝和压缩。【3】

 

关于Arena

Arena是Pytho中一个内存池的实现,我不知道这么说是不是严谨的,但是Arena也是最近的Python版本才加进来的,就是为了支持带有GC的内存管理。

 

当我看代码的时候,不知道是我对某些技巧不了解,还是LOCK就没有实现,我感觉Python的malloc和free摆放着一对儿没有用处的LOCK和UNLOCK,【Python 2.5.2】,不知道是不是因为我没有实际调试的缘故,还没有发现这个宏的玄机。

Raven

名儿,就是一个记性。

老实说,我跟内存泄露做了好多年的斗争了,这次又从中学到了很多东西(也有从其他的资料),结合我曾经写过的Ref<T>类中使用的内存池,这次构造了一个全新的内存池,希望可以有用武之地。

注:

【1】我没有考证过最初的Python源代码,但是印象里最初的Python只有引用计数机制,特别是Ruby 1.9才引入垃圾回收,而以往是采用引用计数技术的。

【2】简直是迫使我查看JVM的源代码了,但是到了64位的平台上,这个结构可能发生更大的变化。

【3】等到我完成了代码,才能兑现这段话,到时候我会Open Source的。

posted on 2009-01-14 14:36  甘草  阅读(669)  评论(0编辑  收藏  举报
Baidu
Google
心寄笔端
TEST
以后我会加上Power By的,先别介意