高并发内存池项目(2)——实现定长池

目录

​编辑

一,定长池介绍

二,基本结构

三成员

两函数

代码结构:

三,具体实现

1,New的具体实现

2,Delete的具体实现

四,测试

测试代码:

 测试结果:

 

一,定长池介绍

这个模块是一个快速生成特定大小内存池的模块。是后面实现高并发内存池的重要模块之一。

申请空间时使用的还是malloc函数,但是在后面的测试中会比单纯的malloc更加快速,效率更高。

二,基本结构

三成员

T*_memory:指向大块空间的头部。

int remainSize:标记大块空间的大小,判断是否需要重新申请空间

void*_freelist:delete空间时要将free的空间头插到到这个链表上。

两函数

T* New():用于申请空间,生成T类型对象,优先使用free_list上的空间。

void delete(T*object):释放空间的作用,释放的空间要头插到free_list链表里。

代码结构:

class FixedPoll
{
public:
	T* New()
	{
	   //1,优先使用_freeList里的内存空间
		if (_freelist)
		{

	    }
	   //2,当_freeList上没有free的地址  
		else
		{
			// 内存不足时先申请大块空间
			if (_remainSize < sizeof(T))
			{

			}
			else
			{

			}

		}
	}

	void Delete(T* obj)
	{
		//使用头插的方式来记录free后的对象的地址
	}

private:
	T* _memory = nullptr;//指向大块的内存
	int _remainSize = 0;//用于标记内存的剩余大小
	void* _freeList = nullptr;//用于存放释放后的内存地址
};

三,具体实现

1,New的具体实现

T* New()
	{
	   //1,优先使用_freeList里的内存空间
		//先定义一个指针对象
		T* obj = nullptr;
		if (_freeList)
		{
			//前面的指针大小空间记录下一个节点的地址
			void* next = *(void**)_freeList;
            //将空间读取出来给obj对象
			obj = (T*)_freeList;
            //freeList到下一个节点上
			_freeList = next;
	    }
	   //2,当_freeList上没有free的地址  
		else
		{
			//先确定好空间至少要大于指针大小
			int objSize = sizeof(T*) > sizeof(T) ? sizeof(T*) : sizeof(T);

			// 内存小于sizeof(T)先申请大块空间
			if (_remainSize < objSize)
			{
				//申请128K大小的内存空间
				_remainSize = 128 * 1024;
				_memory = (char*)malloc(128 * 1024);
				if (_memory == nullptr)
				{
		 			throw std::bad_alloc();
				}

				//将前面的sizeof(T)大小的内存分配给obj
				obj = (T*)_memory;
				_memory += objSize;
				_remainSize -= objSize;
			}
			//
			else
			{
				 //内存空间不小于T时
				obj = (T*)_memory;
				_memory += objSize;
				_remainSize -= objSize;
			}

		}
		return obj;
	}

 实现New功能的注意点:

1,如果free_list存在时要优先使用free_list里面的空间。

2,要保证obj对象的大小大于指针大小,这是为了后面的free_list的实现。

2,Delete的具体实现

void Delete(T* obj)
	{
		//使用头插的方式来记录free后的对象的地址
		//实现头插的方式就是先取出obj的前四个或者八个字节大小的空间存放_freeList的地址,然后再让_freeList指向头部。
		//注意点:要保证obj的大小至少为四个或者八个字节,所以在new时就要确定好。
		*(void**)obj = _freeList;
		_freeList = obj;
	}

Delete实现的注意点:

1,如何适应不同的平台取出的指针的大小都是合法的?使用*(void**)强转的方式。

2,没有next指针如何链接:使用头插的方式。

四,测试

测试代码:

void TestObjectPool()
{
	// 申请释放的轮次
	const size_t Rounds = 3;
	// 每轮申请释放多少次
	const size_t N = 100000;

	//使用new和delete测试
	size_t begin1 = clock();
	std::vector<TreeNode*> v1;
	v1.reserve(N);
	for (size_t j = 0; j < Rounds; ++j)
	{
	for (int i = 0; i < N; ++i)
	{
	v1.push_back(new TreeNode);
	}
	for (int i = 0; i < N; ++i)
	{
	 delete v1[i];
	}
	v1.clear();
	}

	//使用定长内存池测试
	size_t end1 = clock();
	FixedPoll<TreeNode> TNPool;
	size_t begin2 = clock();
	std::vector<TreeNode*> v2;
	v2.reserve(N);
	for (size_t j = 0; j < Rounds; ++j)
	{
		for (int i = 0; i < N; ++i)
		{
			v2.push_back(TNPool.New());
		}
		for (int i = 0; i < N; ++i)
		{
			TNPool.Delete(v2[i]);
		}
		v2.clear();
	}
	size_t end2 = clock();
	cout << "new cost time:" << end1 - begin1 << endl;
	cout << "object pool cost time:" << end2 - begin2 << endl;
}

 测试结果:

可以看到我们实现的定长池的速度明显快于new的速度。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值