07 细节优化(1)

        经过前面几个章节的设计的主体就已经完成了,接下来便是测试与优化的工作。

        首先在设计上,有以下可以改进的地方:

一、项目中有大量的地方使用了new运算符

        主要是在堆中开辟Span结构体,还有给每个线程在堆中开辟ThreadCache对象的地方。此时00.基础——简单定长内存池章节中的定长内存池就可以派上用场了,将高并发内存池中一些用到堆的工件地方,都向定长内存池申请即可。从定长内存池中申请内存要比调用new和malloc来得更快。

//定长内存池,用来存放高并发内存池本身需要用到的一些资源,比如Span结构体
template <class T>
class ObjectPool
{
public:
	ObjectPool() :Tsize(sizeof(T))
	{
		size_t tenTsize = 10 * Tsize;
		everyApplyPages = (tenTsize >> FIXEDPOOL_PAGESHIFT)+1;//设置每次向系统申请的页数,至少申请1页
	}
	T* New()
	{
		T* ptr = nullptr;
		if (freelist)
		{
			ptr = (T*)freelist;
			freelist = *(void**)freelist;
		}
		else
		{
			if (leftbytes < Tsize)
			{
				memory = (char*)systemalloc(everyApplyPages);//一次开辟everyApplyPages页
				leftbytes = everyApplyPages << FIXEDPOOL_PAGESHIFT;
			}
			ptr = (T*)memory;
			size_t objectsize = Tsize >= sizeof(void*) ? Tsize : sizeof(void*);
			memory += objectsize;
			leftbytes -= objectsize;
		}
		new(ptr)T;//定位new调用T的默认构造函数
		return ptr;
	}

	void Delete(T* obj)
	{
		obj->~T();//调用析构函数
		*(void**)obj = freelist;
		freelist = (void*)obj;
	}
private:
	char* memory = nullptr;
	int leftbytes = 0;
	void* freelist = nullptr;
	size_t Tsize=0;
	size_t everyApplyPages = 0;
};

二、解决释放内存块时,要给出内存块大小的问题

        每个内存块都是属于一个Span包的,既然如此根据要释放的地址就可以计算出内存块属于哪一页,再根据页号从std::unordered_map<PAGE_ID, Span*> Page_Span;中找到其所属的Span包。可以在Span包中添加一个成员变量,指明这个Span包内每个内存块的大小(大于256KB的情况,就是整个Span包的大小),如此一来,用户释放内存块的时候就不需要再自己传入内存块的大小了。

//内存包span,里面包含了连续页的内存,是中心资源层和页缓存资源层的重要结构
struct Span
{
	PAGE_ID pageID = 0;//包中起始页在内存所有页中的编号(把内存视为一个个页,页编号计算方法为页起始地址/每页的大小)
	size_t counts = 0;//包中页的数量
	Span* prev = nullptr;
	Span* next = nullptr;

	void* freelist = nullptr;//里面存放着span内存包中被切好的内存块的“桶”
	size_t usedBlocks = 0;//已经被分配出去的内存块数量

	bool is_used = false;//标志该Span包是否已经被CentreCache获取
	size_t objectSize = 0;//用来记录该Span包被切割成了多大的内存块,以方便回收内存时无需再传入申请的内存块的大小

	static ObjectPool<Span> SpanPool;//用定长内存池存放所有的Span结构体
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值