一.内存池设计
1.目的:
减少内存碎片,当一个进程长期运行在堆上不停的操作内存会产生内存碎片,导致出现内存分配失败。还有调用malloc/new,系统需要根据“最先匹配”、“最优匹配”或其他算法在内存空闲块表中查找一块空闲内存,调用free/delete,系统可能需要合并空闲内存块,这些会产生额外开销。
2.解决方法:使用内存管理组件,jemalloc和tcmalloc是完善的两个内存管理组件;或者自己实现一个组件。
3.设计思路:
对内存实现管理实际上就是堆管理(malloc),下图是虚拟机内存分布图,内存池的实现主要操作堆的向上增长。两种实现方式定长和不定长。
二.数据结构设计
1.定长实现:将一整块内存分成多个小块,每块大小固定,管理一块4096bytes,分块,如下图
typedef struct mempool_s {
int blocksize; //当前每一块大小
int freecount; //可用块数量
char *free_ptr; //下次开始位置
char *mem; //指向第一块
} mempool_t;
三.接口实现:
1.创建内存池:MEM_PAGE_SIZE为整块内存长度为4096
int memp_create(mempool_t *m, int block_size) {
if (!m) return -1;
m->blocksize = block_size;
m->freecount = MEM_PAGE_SIZE / block_size;
m->mem = (char *)malloc(MEM_PAGE_SIZE);
if (!m->mem) { //NULL
return -2;
}
memset(m->mem, 0, MEM_PAGE_SIZE);
m->free_ptr = m->mem;
int i = 0;
char *ptr = m->mem;
for (i = 0;i < m->freecount;i ++) {
*(char **)ptr = ptr + block_size;
ptr = ptr + block_size;
}
*(char **)ptr = NULL;
return 0;
}
2.内存池销毁
void memp_destory(mempool_t *m) {
if (!m) return ;
free(m->mem);
}
3.内存池分配
void *memp_alloc(mempool_t *m) {
if (!m || m->freecount == 0) return NULL;
void *ptr = m->free_ptr;
m->free_ptr = *(char **)ptr;
m->freecount --;
return ptr;
}
4.内存池释放内存块
void memp_free(mempool_t *m, void *ptr) {
*(char **)ptr = m->free_ptr;
m->free_ptr = (char *)ptr;
m->freecount ++;
}
四.测试
int main() {
mempool_t m;
memp_create(&m, 32);
void *p1 = memp_alloc(&m);
printf("memp_alloc : %p\n", p1);
void *p2 = memp_alloc(&m);
printf("memp_alloc : %p\n", p2);
void *p3 = memp_alloc(&m);
printf("memp_alloc : %p\n", p3);
memp_free(&m, p2);
}
以上是内存池的定长小块实现,后面实现大块。