【高性能内存池】thread cache具体编写 3

前文主要讲解了thread cache的框架和freeList的具体逻辑和实现。本篇文章主要讲解thread cache的具体实现。

  1. 申请内存
  2. 释放内存
  3. memory中没有内存的时候,向central cache申请内存
  4. 当换回来的内存太多时,还内存给central cache

后面的两点要在说完central cache之后再实现,本篇文章暂时不实现。

上一篇文章的链接

1 thread cache代码框架

下面是 thread cache的框架。主要有四个函数,涉及内存的申请和释放。还有一个成员变量是FreeList类型的_freeLists,大小是NFREELIST(我定义为了208)

class ThreadCache
{
public:
	//申请内存
	void* Allocate(size_t size);
	//释放内存
	void Deallocate(void* ptr, size_t size);
	//从中心缓存获取内存
	void* FetchFromCentralCache(size_t index, size_t size);
	// 释放对象时,链表过长时,回收内存回到中心缓存
	void ListTooLong(FreeList& list, size_t size);
private:
	//需要一个_freeList的哈希桶
	FreeList _freeLists[NFREELIST];  //static const size_t NFREELIST = 208;
};

2 申请内存

函数的声明如下,参数传递的是申请的内存大小size

void* Allocate(size_t size);

当传入申请的内存大小size时,根据之前文章所说,不是申请多少给多少,而是根据分配规则和对齐原则来分配。引用上一篇文章所写:

假设申请size字节的内存大小,首先根据size的大小判断应该分配多少个size,例如是size = 19字节,应该分配24字节。其次根据size的大小判断size处于哪一个对齐的区间,例如size = 19,分配为24, 则size < 128,则使用8字节对齐。最终,根据这两个情况,计算出freeList的下标。当size = 24(注意这里是分配为24,虽然我们申请的是19),freeList的下标为3.

再举一个例子,假设size = 300,则根据分配规则,应该分配size = 304字节,根据size的大小判断处于哪一个对齐区间,size = 304,则为16字节对齐。最终计算freeList的下标。当size = 304时,freeList的下标为(304 - 108) / 16 + 16 = 27(这里的计算规则下面会讲),所以freeList的下标应该为27.

总结为三步:
1.根据size大小判断对齐原则(是8字节对齐,还是16字节对齐等)
2.根据对齐原则和size大小判断系统应该分配多少字节。
3.根据系统分配的字节数判断处于freeList的多少号下标。

具体的计算过程上篇文章有讲,十分详细。

具体代码:

void* ThreadCache::Allocate(size_t size)
{
	assert(size <= MAX_BYTES);          
	size_t alignSize = SizeClass::RoundUp(size);   //alignSzie 表示最终内存给的字节数
	size_t index = SizeClass::Index(size);         //index表示内存块在数组中的索引
	
	//找到下标之后,如果_freeLists中有,就直接切出来给系统用
	if (!_freeLists[index].Empty())
	{
		return _freeLists[index].Pop();
	}
	else
	{
		//没有内存块,就去centrleCache获取对象
		return FetchFromCentralCache(index, alignSize);
		//这里没有实现,暂时留着函数
	}
}

3 释放内存

Deallocate的函数声明如下:

void Deallocate(void* ptr, size_t size);

参数列表解读:

1.void* ptr:表示释放的内存的指针
2.size_t size:表示释放的内存的大小

步骤:
1.根据释放内存的大小找到应该存储在freeList中的下标
2.将该段freeList还回到自由链表之中,用Push函数

具体代码的实现:

void ThreadCache::Deallocate(void* ptr, size_t size)
{
	assert(ptr);
	assert(size <= MAX_BYTES);

	//算出来是多少号桶,插入进去
	size_t index = SizeClass::Index(size);
	_freeLists[index].Push(ptr);

	// 当链表长度大于一次批量申请的内存时就开始还一段list给central cache
	if (_freeLists[index].Size() >= _freeLists[index].MaxSize())
	{
	//这里可以先暂时不管,讲解完central cache之后再讲解这里
		ListTooLong(_freeLists[index], size);
	}
}

注意:
这里为什么不需要像Allocate一样先计算分配规则和对齐规则?
因为这里size是之前Allocate计算好的,已经对齐过了。所以可以直接和index相对应。

4 总结

本篇文章主要讲解了·thread cache·申请和释放的过程。
申请的主要过程如下:

1.根据想要申请的size通过分配和对齐原则计算出系统最终会分配的size.
2. 根据系统分配的size计算出freeList的下标index
3. 根据index找到freeList,将这一部分内存Pop()出来。这就是分配的过程

释放的主要过程如下:
1. 将释放的size计算出index
2. 找到freeList[index],将内存还回去,push().

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值