C++内存池设计


一、什么是内存池?为什么要使用内存池?

一次性分配好,使用的时候直接调用,对外提供的是API接口,应用软件直接调用API接口就可以获取到需要的内存空间。在做服务端开发的时候都可以使用内存池。

频繁的对内存进行malloc/free,会产生内存碎片。不断的malloc和free也会影响性能,因为内存操作需要在用户态和内核态之间不断切换。

内存数据也可以用,为什么还要使用内存池?
如果是通过消息队列,把数据push到另外一个线程处理业务的时候,定义的数组是用不了的。此时我们就可以使用内存池传递指针过去。


二、如何实现一个内存池?

我们可以把内存池看作是一个组件,它可以提供API接口,供其他人使用。

2.1 设计步骤

我们可以参考下面的步骤来设计一个内存池:
1)先把组件的基础数据结构定义出来;
2)定义对应的函数,对外提供的API;
3)给出测试函数,告诉其他人API是如何使用的。

比如:内存池给应用程序提供的内存分配API为pmalloc,调用形式:void *p = pmalloc(10)。

2.2 内存池结构体

内存池的每块的内存大小如何界定?如何设计才能在实际应用的时候不会由于内存池中的内存块过小或过大?
这里,我们根据内存页的大小作为界定,一个内存页的大小为4k,小于4k的归为小块内存,大于4k的归为大块内存。
1)小块内存:< 4k
2)大块内存:> 4k


小块内存结构体

扫描二维码关注公众号,回复: 15024205 查看本文章
struct mp_node_s{
    
    
	unsigned char *start;
	unsigned char* end;
	struct node* next;		//4k使用完后,接入用到下一个4k
	int  flag;				//标识内存是否被使用
}

在这里插入图片描述

在这里插入图片描述
比如:申请10个字节, 就会从start开始分配10,然后start往后移动10作为新的开始位置。
回收的时候不做释放,用flag做标记。


大块内存结构体

struct mp_large_s{
    
    
	struct mp_large_s* next;
	void *alloc;
};

大块内存是一页一页处理。我们在使用大块内存时,并不是事先分配好,而是在使用的时候,没有空闲才会去分配。
在这里插入图片描述
使用posix_memalign函数申请大块内存,malloc申请的是小块内存,它们走的是两条不同的路线。使用malloc申请大块内存可能会失败,这时候我们就需要使用posix_memalign函数申请大块内存。


内存池结构体

struct mp_pool_s{
    
    
	size_t max;      //大小内存界定值
	struct mp_node_s *current;
	struct mp_large_s *large;
};

//create pool

//destory pool

//pmalloc/palloc

//free


三、其他开源内存池实现

开源内存池有:tcmalloc/jemalloc
或者nginx中的:ngx_palloc.c / ngx_palloc.h

猜你喜欢

转载自blog.csdn.net/locahuang/article/details/120324954