在某些情况下,需要反复申请和释放大量固定大小的小块内存,如果利用malloc和free的话不但效率低下,而且会使系统产生大量的内存碎片。此时,大都选择使用内存池(Memory Pool)来提高效率。
内存池的原理就是事先申请好一大块内存,然后再在这块内存上分配和释放小块内存。由于允许申请的内存块大小固定,因此不会产生,也不会有分割合并内存块的开销。
下面是我正在编写的GUI系统中所使用的内存池。
首先来看内存池的结构定义:
创建内存池:
由于需要用一个DWORD值来保存内存块的状态,所以在分配内存前先将内存块的大小增加一个DWORD的空间。让后向系统申请内存,并填写MEMPOOL结构。
从内存池中分配内存:
首先通过判断每个内存块头部的DWORD值来找出空闲的内存块。找到以后将其头部的DWORD标记为BH_USED,在将内存块的指针向后偏移一个DWORD后返回。如果没有在内存池中返回,那么就在堆上分配内存块,将状态标记为BH_HEAP后向后偏移一个DWORD并返回。
释放内存块:
释放内存块时将内存块指针向前偏移一个DWORD以获得实际内存块的指针,判断头部DWORD值并根据不同值进行相应的释放动作。若果内存块在堆上,则直接释放到堆上,如果在内存池里,则将内存块状态标记为BH_FREE,并计选出该内存块的索引。如果索引在dwFree之前,则将dwFree设为这块内存的索引,这样使得每次释放后dwFree中保存的都是第一块空闲内存的索引,提高了下一次分配的速度。
释放内存池:
对于多线程的情况,还应该在MEMPOOL结构中增加一个互斥锁。此外,还何以在MEMPOOL结构中增加两个函数指针来实现带构造和析沟和数的内存池。
备注:
由于正在编写的GUI是参考Windows的体系结构,所以代码风格采用了微软的风格。
代码中的MemAlloc,MemFree函数以及各种数据结构均在其它地方定义。