标签:
有些时候为了省空间,我们需要垃圾回收。靠malloc和free的垃圾回收装置效率太低,可能会影响程序效率。其实有一种简单的办法来实现,就是基于循环队列的垃圾回收装置。
一般的系统malloc函数其实都非常先进,可以足够应对大多数应用。但是,它的效率还是比较低的。malloc需要处理不同大小的单元,这些单元需要储存在连续内存空间中以加快访问、提高擦车命中率。即使用并查集维护,在极端条件下的时间复杂度都是O(nα(n))。显然,一次申请大块内存,自己管理是十分有效的。
malloc因为实现复杂,常数较大。
garbage collection算是一个十分形象的名词了。有些被开辟的内存,不用了需要归还可用空间。意思就是,你malloc了的东西,需要free回去;或是new出来的东西自我析构,在析构函数中显性地指定free;或是运行时环境提供的隐形GC,当没有指针指向某个对象时这个对象被GC掉,这些都是提高内存利用率的有效方法。但是仅靠malloc和free无法有效管理内存,易引发内存碎片化。
我喜欢预申请大片内存给节点一类大量动态创建、回收的对象以减轻m/f函数的负担。不可否认的是,不有效管理动态分配仍然会引发内存碎片化。但是对于这类单元大小(即每次分配的内存大小)固定的结点类对象是有完全垃圾回收、分配方案的。也就是,无论什么样的操作序列,只要内存大小大于等于任何一时刻的总节点大小,都能满足请求。
写个普通的GC,可以用栈来维护。但是,这样做空间利用率可能会非常低。
可以在队列两头开辟释放内存。
同理可写循环队列GC器
完全GC的实现非常简单,核心思想是用循环队列维护指针使已分配的内存在循环队列上连续,而不一定要在内存本身上连续。基于RAM模型,这个办法效果很好。
struct sn{ data dat; int puid; }; typedef sn* snp; struct s_buf{ #define ccq(x) x=(++x==tbuf)?0:x; sn buf[tbuf]; int f,e,id[tbuf]; inline snp alloc(){ ccq(e) (buf+id[e])->puid=id[e]; return buf+id[e]; } inline void free(snp node){ ccq(f) id[f]=node->puid; } inline void init(){ for(int i=0;i<tbuf;++i) id[i]=i; } } sbuf;
证明很简单,留作习题。
标签:
原文地址:http://www.cnblogs.com/tmzbot/p/4373514.html