高并发项目(一):内存池的概念/定长内存池的实现

目录

一、池化技术及其优势

1.1什么是池化技术

1.2内存池的作用

 1.3malloc的原理

二、定长内存池的实现


一、池化技术及其优势

1.1什么是池化技术

所谓 池化技术 ,就是程序先向系统申请过量的资源,然后自己管理,以备不时之需。之所以要申请过量的资源,是因为每次申请该资源都有较大的开销,不如提前申请好了,这样使用时就会变得非常快捷,大大提高程序运行效率。在计算机中,有很多使用“ 这种技术的地方,除了内存池,还有连接池、线程池、对象池等。以服务器上的线程池为例,它的主要思想是:先启动若干数量的线程,让它们处于睡眠状态,当接收到客户端的请求时,唤醒池中某个睡眠的线程,让它来处理客户端的请求,当处理完这个请求,线程又进入睡眠状态。

1.2内存池的作用

内存池是指程序预先从操作系统申请一块足够大内存,此后,当程序中需要申请内存的时候,不是直接向操作系统申请,而是直接从内存池中获取;同理,当程序释放内存的时候,并不真正将内存返回给操作系统,而是返回内存池。当程序退出(或者特定时间)时,内存池才将之前申请的内存真正释放。内存池主要解决的当然是效率的问题,其次如果作为系统的内存分配器的角度,还需要解决一下内存碎片的问题。

内存碎片分为内部碎片和外部碎片:

  • 外部碎片是一些空闲的小块内存区域,由于这些内存空间不连续,以至于合计的内存足够,但是不能满足一些内存分配申请需求。
  • 内部碎片是由于一些对齐的需求,导致分配出去的空间中一些内存无法被利用。

 1.3malloc的原理

malloc 就是一个内存池。 malloc() 相当于向操作系统 批发 了一块较大的内存空间,然后 零售 给程
序用。当全部 售完 或程序有大量的内存需求时,再根据实际需求向操作系统 进货 malloc 的实现方式有很多种,一般不同编译器平台用的都是不同的。比如windows vs 系列用的微软自己写的一套,linux gcc用的 glibc 中的 ptmalloc 。下面有几篇关于这块的文章,大概可以去简单看看了解一下,关于ptmalloc,学完我们的项目以后,有兴趣大家可以去看看他的实现细节。

二、定长内存池的实现

#pragma once
#include <iostream>
#include <vector>
#include <time.h>
using std::cout;
using std::endl;


template<class T>
class Pool
{
public:
	T* New()
	{
		T* obj;
		if (_freeList)//如果链表有数据,就直接返回链表头节点数据
		{
			void* next = *((void**)_freeList);//保存链表头节点前4/8个字节中存放的下一个节点的地址
			obj = (T*)_freeList;//将第一个节点强转成T*类型
			_freeList = next;//头节点指向下一个
		}
		else
		{
			if (sizeof(_memory) < sizeof(T))//如果此时内存池中没有空间/空间满了
			{
				_remainBytes = 128 * 1024;
				_memory = (char*)malloc(_remainBytes);
				if (_memory == nullptr)
				{
					throw std::bad_alloc();
				}
			}
			obj = (T*)_memory;//从内存池头部拿取T大小的内存
			size_t objSize = sizeof(T) < sizeof(void*) ? sizeof(void*) : sizeof(T*);
			//如果T的类型还没指针大,直接返回一个指针的大小,方便后期回收插入_freelist

			_memory += objSize;//向后移动
			_remainBytes -= objSize;//内存--
		}
		new(obj)T;//定位new
		return obj;
	}
	void Delete(T* obj)
	{
		obj->~T();//先析构T类型
		
		//将obj转成void**再解引用,这样不管32位平台还是64位平台都可以准确拿到地址的大小
		*(void**)obj = _freeList;//obj的前4/8位存放下一个节点的地址
		_freeList = obj;//_freeList指向obj,此时obj就是头节点,头插完成
	}
private:
	char* _memory = nullptr;//内存池地址
	size_t _remainBytes = 0;//当前内存池所剩容量
	void* _freeList = nullptr;//经过回收的内存碎片的头指针(以链表的形式)
};

  • 5
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

C+五条

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值