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


    有些时候为了省空间,我们需要垃圾回收。靠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;
    

    证明很简单,留作习题。

  • 相关阅读:
    【C#】C#8.0常用新特性
    【Docker】Asp.net core在docker容器中的端口问题
    【gRPC】ProtoBuf 语言快速学习指南
    【日常排雷】 .Net core 生产环境appsetting读取失败
    【gRPC】 在.Net core中使用gRPC
    raspbian buster阿里镜像
    管道通信
    关于utf8mb4的使用
    ef core数据迁移的一点小感悟
    windows 端口转发
  • 原文地址:https://www.cnblogs.com/tmzbot/p/4373514.html
Copyright © 2020-2023  润新知