内存池是什么?
内存池(Memory Pool)是一种内存分配方式,又被称为固定大小区块规划(fixed-size-blocks allocation)。通常我们习惯直接使用new、malloc等API申请分配内存,这样做的缺点在于:由于所申请内存块的大小不定,当频繁使用时会造成大量的内存碎片并进而降低性能。
内存池如何实现?
1.内存结构
typedef struct {
struct list_head list;
int fd; // Unix系映射文件句柄
int tid;
} Heap;
typedef struct {
unsigned int unMem_flg; // 块标志
unsigned int unMem_size; // 块大小
} Heapinf;
#define ALLOCATE_MEM_ALL_BLOCK 0xFFFFFFFF //不可分区的块
#define ALLOCATE_MEM_SEP_BLOCK 0x11111111 //可分区的块
#define ALLOCATE_MEM_STATUS_USED 0x22222222 //已使用的块
#define ALLOCATE_MEM_STATUS_FREE 0x33333333 //未使用的块
2.接口
class HeapManage {
public:
// 从内存池分配指定内存
static void *_allocate(unsigned int size, unsigned int tid);
// 将内存返回内存池
static int _release(void *ptr);
private:
struct list_head head;
HeapManage();
virtual ~HeapManage(){};
// 获取堆内存/虚拟内存
static void *_allocate_p(int mode, unsigned int unMemSize, int mapfd);
// 释放堆内存/虚拟内存
static void _release_p(list_head *head);
// 单例模式
static HeapManage &getInstance();
static HeapManage *sInstance;
class HeapFree {
public:
HeapFree() {}
virtual ~HeapFree();
};
friend class HeapManage::HeapFree;
static HeapFree mHeapFree;
};
#define allocate(size) HeapManage::_allocate(size, 0)
#define release(ptr) HeapManage::_release(ptr)
3.分配
void *HeapManage::_allocate(unsigned int ulAreaSize, unsigned int tid) {
void *pReturn_code = NULL;
......
unMemAct_size = length_align(ulAreaSize);
head = &getInstance().head;
pHeap = list_entry(head->next, Heap, list);
iMem_fd = pHeap->fd;
if (unMemAct_size > 64 * 1024) {
pHeap = (Heap *)_allocate_p(
0, unMemAct_size + sizeof(Heap) + sizeof(Heapinf) * 2, iMem_fd);
if (pHeap != NULL) {
list_add_tail(&pHeap->list, head);
pHeap->tid = tid;
pReturn_code = (char *)pHeap + sizeof(Heap) + sizeof(Heapinf);
} else {
;
}
goto EXIT;
}
pWorkInf = (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
do {
pHeapInf = (Heapinf *)((char *)pHeap + sizeof(Heap));
if (pHeapInf->unMem_flg == ALLOCATE_MEM_ALL_BLOCK) {
if (pHeap->list.next != head) {
pHeap = list_entry(pHeap->list.next, Heap, list);
pWorkInf = (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
} else {
pHeap = (Heap *)_allocate_p(1, 0, iMem_fd);
if (pHeap != NULL) {
list_add_tail(&pHeap->list, head);
pWorkInf =
(Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
} else {
;
}
}
} else if (pHeap->tid != tid) {
if (pHeap->list.next != head) {
... ...
} else {
... ...
}
} else if (pWorkInf->unMem_flg == ALLOCATE_MEM_STATUS_FREE) {
if (pWorkInf->unMem_size >= unMemAct_size + sizeof(Heapinf) * 2) {
/*** 从空闲区取出期待大小的块 ***/
/*** 重新计算空闲区 ***/
......
iMem_flg = 1;
......
} else {
pWorkInf = (Heapinf *)((char *)pWorkInf + sizeof(Heapinf) * 2 +
pWorkInf->unMem_size);
}
} else if (pWorkInf->unMem_flg == ALLOCATE_MEM_STATUS_USED) {
pWorkInf = (Heapinf *)((char *)pWorkInf + sizeof(Heapinf) * 2 +
pWorkInf->unMem_size);
} else if (pWorkInf->unMem_flg == ALLOCATE_MEM_SEP_BLOCK) {
if (pHeap->list.next != head) {
pHeap = list_entry(pHeap->list.next, Heap, list);
pWorkInf = (Heapinf *)((char *)pHeap + sizeof(Heap) + sizeof(Heapinf));
} else {
... ...
}
} else {
goto EXIT;
}
} while (iMem_flg != 1);
EXIT:
return pReturn_code;
}
4.释放
int HeapManage::_release(void *ptr) {
int iReturn_code;
......
iReturn_code = 0;
if (ptr == 0) goto EXIT;
head = &getInstance().head;
inf = (Heapinf *)((char *)ptr - sizeof(Heapinf));
switch (inf->unMem_flg) {
case ALLOCATE_MEM_STATUS_USED:
pwk_inf = inf;
do {
pwk_inf = (Heapinf *)((char *)pwk_inf + pwk_inf->unMem_size +
sizeof(Heapinf) * 2);
if (pwk_inf->unMem_flg != ALLOCATE_MEM_STATUS_FREE &&
pwk_inf->unMem_flg != ALLOCATE_MEM_STATUS_USED &&
pwk_inf->unMem_flg != ALLOCATE_MEM_SEP_BLOCK) {
iReturn_code = -1;
goto EXIT;
}
} while (pwk_inf->unMem_flg != ALLOCATE_MEM_SEP_BLOCK);
pHeap = (Heap *)((char *)pwk_inf -
(sizeof(Heap) + sizeof(Heapinf) + pwk_inf->unMem_size));
unMemFree_size = inf->unMem_size;
pwk_inf = (Heapinf *)((char *)inf + inf->unMem_size + sizeof(Heapinf));
if (pwk_inf->unMem_flg != ALLOCATE_MEM_STATUS_USED ||
pwk_inf->unMem_size != unMemFree_size) {
iReturn_code = -1;
goto EXIT;
}
unMemNext_free_flg = 0;
pwk_inf = (Heapinf *)((char *)pwk_inf + sizeof(Heapinf));
// 根据释放区域前后区域是否需要合并,重新计算空闲区大小
... ...
... ...
if (pHeap->list.prev == pHeap->list.next) {
goto EXIT;
} else {
inf = (Heapinf *)((char *)pHeap + sizeof(Heap));
if (inf->unMem_size == (inf + 1)->unMem_size + sizeof(Heapinf) * 2) {
;
} else {
goto EXIT;
}
}
break;
case ALLOCATE_MEM_ALL_BLOCK:
pHeap = (Heap *)((char *)inf - sizeof(Heap));
break;
default:
iReturn_code = -1;
goto EXIT;
}
// 释放空内存池
unMemFree_size = ((Heapinf *)(pHeap + 1))->unMem_size;
unMemFree_size += sizeof(Heap) + sizeof(Heapinf) * 2;
list_del(&pHeap->list);
#if defined(WIN32)
hGlobal = GlobalHandle(pHeap);
GlobalUnlock(hGlobal);
GlobalFree(hGlobal);
#else
munmap(pHeap, unMemFree_size);
#endif
EXIT:
return iReturn_code;
}