固定单元大小的完全垃圾回收机制

有些时候为了省空间,我们需要垃圾回收。靠malloc和free的垃圾回收装置效率太低,可能会影响程序效率。其实有一种简单的办法来实现,就是基于循环队列的垃圾回收装置。

为什么malloc效率低下

一般的系统malloc函数其实都非常先进,可以足够应对大多数应用。但是,它的效率还是比较低的。malloc需要处理不同大小的单元,这些单元需要储存在连续内存空间中以加快访问、提高擦车命中率。即使用并查集维护,在极端条件下的时间复杂度都是O(nα(n))。显然,一次申请大块内存,自己管理是十分有效的。

malloc因为实现复杂,常数较大。

如何做垃圾回收

garbage collection算是一个十分形象的名词了。有些被开辟的内存,不用了需要归还可用空间。意思就是,你malloc了的东西,需要free回去;或是new出来的东西自我析构,在析构函数中显性地指定free;或是运行时环境提供的隐形GC,当没有指针指向某个对象时这个对象被GC掉,这些都是提高内存利用率的有效方法。但是仅靠malloc和free无法有效管理内存,易引发内存碎片化。

自己做资源分配、垃圾回收

我喜欢预申请大片内存给节点一类大量动态创建、回收的对象以减轻m/f函数的负担。不可否认的是,不有效管理动态分配仍然会引发内存碎片化。但是对于这类单元大小(即每次分配的内存大小)固定的结点类对象是有完全垃圾回收、分配方案的。也就是,无论什么样的操作序列,只要内存大小大于等于任何一时刻的总节点大小,都能满足请求。

1 普通GC

写个普通的GC,可以用栈来维护。但是,这样做空间利用率可能会非常低。

2 队列GC

可以在队列两头开辟释放内存。

同理可写循环队列GC器

3 完全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;

证明很简单,留作习题。

原文地址:https://www.cnblogs.com/tmzbot/p/4373514.html