Inherited from NULL
Inherited by NULL
Friend class NULL
Description
常用的malloc/free 和 new/delete 在堆上申请和释放内存都有一定的额外开销。开销来自维护 内存空闲块表。
malloc和new 申请堆内存时,首先查找内部维护的内存空闲块表,并且需要根据一定的算法(例如分配最先找到的不小于申请大小的内存块给请求者,或者分配最适于申请大小的内存块,或者分配最大空闲的内存块等)找到合适大小的空闲内存块。如果该空闲内存块过大,还需要切割成已分配的部分和较小的空闲块。然后系统更新内存空闲块表,完成一次内存分配。
类似地,在free和delete释放内存时,系统把释放的内存块重新加入到空闲内存块表中。如果有可能的话,可以把相邻的空闲块合并成较大的空闲块。默认的内存管理函数还考虑到多线程的应用,需要在每次分配和释放内存时加锁,同样增加了开销。
可见,如果应用程序频繁地在堆上分配和释放内存,则会导致性能的损失。并且会使系统中出现大量的内存碎片,降低内存的利用率。连续的new/delete操作,一大块内存肯能就被分割成小的内存分配出去了,这些小的内存都是不连续的。当再去分配大的连续内存的时候,尽管剩余内存的总和可能大于所要分配的内存大小,但系统就找不到连续的内存了,所以导致分配错误。默认的分配和释放内存算法自然也考虑了性能,然而这些内存管理算法的通用版本为了应付更复杂、更广泛的情况,需要做更多的额外工作。而对于某一个具体的应用程序来说,适合自身特定的内存分配释放模式的自定义内存池则可以获得更好的性能。
XT库中XMemPool的类就是一种这样的内存池,它可以通过调用系统的内存分配函数预先一次性申请适当大小的内存作为一个内存池,并为这个内存池类或结构体定义一些分配和释放内存块的成员函数。之后应用程序自己对内存的分配和释放则可以通过这个内存池类及其成员函数来完成。
只有当内存池大小需要动态扩展时,才需要再调用系统的内存分配函数,其他时间对内存的一切操作都在应用程序的掌控之中。
与系统内存管理相比,XMemPool内存池的操作非常迅速,性能优化方面的优点如下:
XMemPool内存池由若干个相同大小的内存片(Chunk)组成,在创建内存池对象时,仅创建一个Chunk,在后面的内存分配中,如果这个Chunk的空间已经用尽,将创建一个新的Chunk并添加到Chunk链表中。Chunk的尺寸是内存池的固有属性,仅可以在构造函数中指定。一个Chunk是一块连续内存,不同Chunk之间不需要连续。从内存池中申请的内存返回内存池之后,该内存成为Chunk的一个内存块(Block),并且根据Block的大小将该内存地址添加到对应的可重分配内存块链表(Reallocatable Block List,RBL)中。RBL存储在第一个Chunk中,增加的Chunk仅在Chunk的头部存储下一个Chunk的首地址。内存池会记录未分配区域的首地址,申请内存时首先从RBL中寻找,如果该链表为空,则从内存池的未分配区域分配。
XT中的内存池有两种使用模式,一种是变长模式,指内存池中有多种长度的Block,申请和返回内存时会根据给定的长度与不小于该长度的最小Block长度取齐;大于最大Block长度(32位操作系统时为4096 Byte)的内存将直接从系统申请或返回给系统。另一种是定长模式,指内存池中只有一种长度的Block,每次分配内存时均按照该Block的长度来分配。为区别于变长模式下的内存块(Block),以后称定长模式下的内存块(Block)为内存单元(Unit)。
Members
Public interface
Private interface
ulong m_ulChunkSize
Chunk大小,XMemPool可以有多个Chunk,单位为字节
ulong m_ulChunkFreeSize
最后一个Chunk里未分配的内存大小,单位为字节
ulong m_ulUnitSize
内存池为定长模式时有效,每个Block的大小,单位为字节
void ** m_pRBLTable
第一个Chunk的首地址
void * m_pFreeHeader
最后一个Chunk未分配空间的首地址
LinkNext * m_pChunkList
存储Chunk首地址的链表
XMemPool(ulong chunkSize)
XMemPool(ulong unitCnt,ulong unitSize)
void * alloc(ulong size)
void * allocUnit()
void release(void * p,ulong size = 0)
void dumpPool(const char * fname)
void reset()
bool isInPool(void * p)
XMemPool(XMemPool &)
void operator = (XMemPool &)
void * addChunk()
void addToRBL(void * p, ulong size)
void addUnitToRBL(void *p)
void * allocFromRBL(ulong size)