内存池的原理
内存池是一种 预先分配和管理内存 的技术,主要用于 提高内存分配效率,减少内存碎片,并优化程序性能。
预先分配一大块内存(称为“池”),避免频繁调用 malloc/new 和 free/delete。
自主管理内存分配和释放,减少系统调用的开销。
减少内存碎片,提高内存利用率。
本贴主要介绍可变长内存池的设计及实现
小内存分配

当用户申请的内存是小内存时(这里的小内存指的是小于small_buffer_capacity),检查small_block组成的链表,图示的是一开始初始化memory_pool的样子,如果余下内存空间足够放得下用户申请的内存(可以理解为图中绿色部分的内存量大于申请内存量)那么就将small_block的可用指针移动。(这里不理解数据结构中各个变量的作用,先不着急,接下来会详细阐述,这一部分请尽量体会内存池的运行逻辑,加油)。
大内存分配

当用户的内存过大(大于small_buffer_capacity时)就需要使用big_block来管理这些内存块,在内存池看来,各个数据结构是需要占据小内存的,需要当作申请小内存来处理,而申请的大内存就直接开辟一个大内存即可,形成一个大内存链来管理。
扩容
其实聪明的你应该会有疑问,当我申请小内存时,我原先预先开辟的内存块不够用了怎么办?那么,我们就需要动态扩容,同样再开辟一个内存块,将新的small_block来管理这个内存块即可。

好啦,你已经了解了内存池的运行模式啦,那就动手设计吧

内存池各个数据结构设计
由于nignix中内存池是纯C语言书写的,这里我们用C++进行改写,那么我们就需要预料到,内存池类是不是在运行过程中只保留一份,不必存在多个对象,那么其内部的成员函数怎么办?该如何设计呢?是不是很熟悉,对!就是单例模式!我们只需要把成员函数static一下,那么它们就独立于内存池类了,并且只会保留一份,不必占用过多内存,什么?不知道设计模式,害,等我更新。
内存池类结构
class memory_pool {
public:
size_t small_buffer_capacity;//小块大小,作为初始数据
small_block* cur_usable_small_block;//当前可用小块
big_block* big_block_start;//大块头
small_block small_block_start[0];//小块头
static memory_pool* createPool(size_t capacity);//创建内存池
static void destroyPool(memory_pool* pool);//销毁内存池
static char* createNewSmallBlock(memory_pool* pool, size_t size);//创建小块
static char* mallocBigBlock(memory_pool* pool, size_t size);//创建大块
static void* poolMalloc(memory_pool* pool, size_t size);//申请块api
static void freeBigBlock(memory_pool* pool, char* buffer_ptr);//free函数
};
管理小内存的结构
class small_block {
public:
char* cur_usable_buffer;//当前可以使用的小块地址
char* buffer_end;//地址范围的末尾
small_block* next_block;//下一个可以使用的块
int no_enough_times;//寻找失

最低0.47元/天 解锁文章
303

被折叠的 条评论
为什么被折叠?



